/**
 * 材质编辑器面板
 * 左侧显示项目材质列表，右侧显示材质参数编辑界面
 */

import * as THREE from 'three';
import { getMaterialLibraryManager } from '../model-library/MaterialLibraryManager.js';
import { addMaterialReference, removeMaterialReference } from '../utils/materialReferenceHelper.js';

export class MaterialEditorPanel {
    constructor() {
        this.projectId = null;
        this.materialLibraryManager = null;
        this.materials = [];
        this.selectedMaterial = null;
        this.selectedMaterialData = null;
        
        // 预览相关
        this.previewScene = null;
        this.previewCamera = null;
        this.previewRenderer = null;
        this.previewMesh = null;
        this.animationId = null;
        
        // 未保存状态追踪
        this.hasUnsavedChanges = false;
        
        // ⭐ 材质使用追踪系统
        // 记录每个材质被哪些场景的哪些节点的哪些mesh使用
        // Map<materialId, Map<sceneId, Map<nodeId, Set<meshUuid>>>>
        this.materialUsageMap = new Map();
        
        this.init();
    }
    
    /**
     * 初始化
     */
    async init() {
        // 获取当前项目ID（从projectManager获取）
        this.projectId = window.projectManager?.getCurrentProject()?.id;
        
        if (!this.projectId) {
            console.warn('⚠️ 无法获取项目ID');
            return;
        }
        // 初始化材质库管理器
        this.materialLibraryManager = getMaterialLibraryManager(this.projectId);
        
        // 暴露到全局，供onclick使用
        window.materialEditorPanel = this;
        
        // 注册全局材质刷新函数
        window.forceRefreshMaterialDisplays = async (reason = '') => {
            if (window.materialEditorPanel) {
                try {
                    await window.materialEditorPanel.refreshMaterialUsageAfterNodeChange();
                } catch (error) {
                    console.error(`❌ 材质面板刷新失败:`, error);
                }
            }
        };
        
        // 渲染界面
        this.renderUI();
        
        // 加载材质列表
        await this.loadMaterials();
        
        // 绑定事件
        this.bindEvents();
    }
    
    /**
     * 渲染UI
     */
    renderUI() {
        const panel = document.getElementById('material-editor-body');
        if (!panel) {
            console.error('❌ 材质编辑器面板容器不存在');
            return;
        }
        
        panel.innerHTML = `
            <div class="material-editor-layout">
                <!-- 左侧：材质列表 -->
                <div class="material-list-section">
                    <div class="material-search-box">
                        <input type="text" id="material-search-input" placeholder="搜索材质..." />
                    </div>
                    
                    <!-- 筛选选项 -->
                    <div class="material-filter-box">
                        <label class="material-filter-checkbox">
                            <input type="checkbox" id="material-filter-current-scene" />
                            <span>只显示当前场景使用的</span>
                        </label>
                    </div>
                    
                    <div class="material-list-scroll">
                        <div id="material-list-items" class="material-list-items">
                            <!-- 材质列表将在这里渲染 -->
                        </div>
                    </div>
                </div>
                
                <!-- 右侧：材质参数编辑 -->
                <div class="material-params-section">
                    <div id="material-params-content" class="material-params-content">
                        <div class="material-empty-state">
                            <div class="empty-icon">🎨</div>
                            <div class="empty-text">请选择一个材质进行编辑</div>
                            <div class="empty-hint">或者创建一个新材质</div>
                        </div>
                    </div>
                </div>
            </div>
            
            <!-- 新建材质模态框 -->
            <div class="material-modal" id="create-material-modal">
                <div class="material-modal-content">
                    <div class="material-modal-header">
                        <h3>新建材质</h3>
                        <button class="material-modal-close" id="close-create-material-modal">×</button>
                    </div>
                    <div class="material-modal-body">
                        <div class="material-form-group">
                            <label>材质名称 <span class="required">*</span></label>
                            <input type="text" id="new-material-display-name" placeholder="例如：红色金属、玻璃材质等" />
                            <div class="material-form-hint">将创建基于物理的渲染材质（Physical Material）</div>
                        </div>
                    </div>
                    <div class="material-modal-footer">
                        <button class="material-btn-secondary" id="cancel-create-material">取消</button>
                        <button class="material-btn-primary" id="confirm-create-material">创建</button>
                    </div>
                </div>
            </div>
            
            <!-- 复制材质模态框 -->
            <div class="material-modal" id="duplicate-material-modal">
                <div class="material-modal-content">
                    <div class="material-modal-header">
                        <h3>复制材质</h3>
                        <button class="material-modal-close" id="close-duplicate-material-modal">×</button>
                    </div>
                    <div class="material-modal-body">
                        <div class="material-form-group">
                            <label>新材质名称 <span class="required">*</span></label>
                            <input type="text" id="duplicate-material-display-name" placeholder="例如：红色金属 (副本)" />
                            <div class="material-form-hint">为复制的材质指定一个新名称</div>
                        </div>
                    </div>
                    <div class="material-modal-footer">
                        <button class="material-btn-secondary" id="cancel-duplicate-material">取消</button>
                        <button class="material-btn-primary" id="confirm-duplicate-material">复制</button>
                    </div>
                </div>
            </div>
        `;
    }
    
    /**
     * 加载材质列表
     */
    async loadMaterials() {
        try {
            this.materials = await this.materialLibraryManager.loadMaterials();
            
            // ⭐ 构建材质使用映射（扫描所有场景）
            await this.buildMaterialUsageMap();
            
            this.renderMaterialList();
        } catch (error) {
            console.error('❌ 加载材质列表失败:', error);
        }
    }
    
    /**
     * 渲染材质列表
     */
    renderMaterialList(filterText = '') {
        const container = document.getElementById('material-list-items');
        if (!container) return;
        
        // ⭐ 安全检查：确保 materials 是数组
        if (!this.materials || !Array.isArray(this.materials)) {
            console.warn('⚠️ materials 不是有效的数组:', this.materials);
            container.innerHTML = `
                <div class="material-list-empty">
                    <div class="empty-icon">⚠️</div>
                    <div class="empty-text">材质数据加载失败</div>
                </div>
            `;
            return;
        }
        
        // 获取筛选选项
        const filterCurrentSceneCheckbox = document.getElementById('material-filter-current-scene');
        const onlyShowCurrentScene = filterCurrentSceneCheckbox ? filterCurrentSceneCheckbox.checked : false;
        
        // 获取当前场景ID
        const currentSceneId = window.manager?.getCurrentSceneName();
        
        // 过滤材质
        const filteredMaterials = this.materials.filter(mat => {
            // ⭐ 跳过无效的材质对象
            if (!mat) return false;
            // 文本搜索过滤
            if (filterText) {
                const searchText = filterText.toLowerCase();
                const matchesSearch = (mat.name && mat.name.toLowerCase().includes(searchText)) ||
                                    (mat.displayName && mat.displayName.toLowerCase().includes(searchText));
                if (!matchesSearch) return false;
            }
            
            // 🎯 当前场景筛选
            if (onlyShowCurrentScene && currentSceneId) {
                // ✅ 从材质JSON的usedByMeshes字段判断
                if (!mat.usedByMeshes || !Array.isArray(mat.usedByMeshes)) {
                    return false;
                }
                // 检查是否包含当前场景的节点
                const usedInCurrentScene = mat.usedByMeshes.some(ref => ref.sceneId === currentSceneId);
                if (!usedInCurrentScene) {
                    return false;
                }
            }
            
            return true;
        });
        
        if (filteredMaterials.length === 0) {
            container.innerHTML = `
                <div class="material-list-empty">
                    <div class="empty-icon">📦</div>
                    <div class="empty-text">暂无符合条件的材质</div>
                </div>
            `;
            return;
        }
        
        container.innerHTML = filteredMaterials.map(mat => {
            // 获取材质使用信息
            const usage = this.getMaterialUsage(mat.displayName);
            const usageText = usage.count > 0 ? `${usage.count}处使用` : '未使用';
            
            return `
            <div class="material-list-item ${this.selectedMaterial?.displayName === mat.displayName ? 'active' : ''}" 
                 data-material-id="${mat.displayName}">
                <div class="material-item-info">
                    <div class="material-item-name-container">
                        <div class="material-item-name-display" title="双击编辑名称">${mat.displayName || mat.name}</div>
                        <input type="text" class="material-item-name-input" value="${mat.displayName || mat.name}" style="display: none;" />
                    </div>
                    <div class="material-item-meta">
                        <span class="material-type-tag">${mat.type || 'Standard'}</span>
                        <span class="material-usage-tag">${usageText}</span>
                    </div>
                </div>
            </div>
        `}).join('');
        
        // 绑定点击和双击事件
        container.querySelectorAll('.material-list-item').forEach(item => {
            const materialId = item.dataset.materialId;
            
            // 单击选择材质
            item.addEventListener('click', (e) => {
                // 如果点击的是输入框，不触发选择
                if (e.target.classList.contains('material-item-name-input')) return;
                this.selectMaterial(materialId);
            });
            
            // 双击重命名功能已移除
        });
    }
    
    /**
     * ⭐ 节点变化后刷新材质使用计数
     * @param {Object} node - 被删除或修改的节点
     */
    async refreshMaterialUsageAfterNodeChange(node) {
        try {
            // 重新加载材质列表
            this.materials = null;
            this.materials = await this.materialLibraryManager.loadMaterials({ forceRefresh: true });
            
            // 更新当前选中材质的数据
            if (this.selectedMaterial && this.selectedMaterial.displayName) {
                const updatedMaterial = this.materials.find(m => 
                    m.displayName === this.selectedMaterial.displayName
                );
                if (updatedMaterial) {
                    this.selectedMaterialData = updatedMaterial;
                }
            }
            
            // 刷新UI显示
            this.refreshMaterialUsageDisplay();
        } catch (error) {
            console.error('❌ 材质面板刷新失败:', error);
        }
    }
    
    /**
     * ⭐ 刷新材质列表中的使用情况标签（不重新渲染整个列表）
     */
    refreshMaterialUsageDisplay() {
        const container = document.getElementById('material-list-items');
        if (!container) return;
        
        // 更新每个材质的使用情况标签
        container.querySelectorAll('.material-list-item').forEach(item => {
            const materialId = item.dataset.materialId;
            if (!materialId) return;
            
            const usage = this.getMaterialUsage(materialId);
            const usageText = usage.count > 0 ? `${usage.count}处使用` : '未使用';
            
            const usageTag = item.querySelector('.material-usage-tag');
            if (usageTag) {
                usageTag.textContent = usageText;
            }
        });
    }
    
    /**
     * 选择材质
     */
    async selectMaterial(materialId) {
        // 检查是否有未保存的修改
        if (this.hasUnsavedChanges) {
            // 显示确认对话框，等待用户选择
            const userChoice = await this.showUnsavedChangesDialog();
            
            if (userChoice === 'save') {
                // 用户选择保存
                await this.saveMaterial();
                // 如果保存后还有未保存状态（保存失败），则不切换
                if (this.hasUnsavedChanges) {
                    return;
                }
            } else if (userChoice === 'cancel') {
                // 用户取消切换
                return;
            }
            // 如果是 'discard'，则继续切换不保存
        }
        
        try {
            // 加载材质数据
            this.selectedMaterialData = await this.materialLibraryManager.getMaterial(materialId);
            this.selectedMaterial = this.materials.find(m => m.displayName === materialId);
            
            // 重置未保存状态
            this.hasUnsavedChanges = false;
            
            // 更新列表中的选中状态
            document.querySelectorAll('.material-list-item').forEach(item => {
                item.classList.toggle('active', item.dataset.materialId === materialId);
            });
            
            // 渲染参数编辑界面
            this.renderMaterialParams();
            
            // ⭐ 如果预览窗口是打开的，同步更新预览
            // (预览会通过 bindParamEvents 自动更新)
            
        } catch (error) {
            console.error('❌ 加载材质失败:', error);
            if (window.showManageMessage) {
                window.showManageMessage('加载材质失败: ' + error.message, 'error');
            }
        }
    }
    
    /**
     * 渲染材质参数编辑界面
     */
    async renderMaterialParams() {
        const container = document.getElementById('material-params-content');
        if (!container || !this.selectedMaterialData) return;
        
        const mat = this.selectedMaterialData;
        
        // 加载所有贴图数据以获取贴图名称
        let textureNameMap = {};
        try {
            const textures = await this.loadProjectTextures();
            textureNameMap = textures.reduce((map, tex) => {
                map[tex.id] = tex.displayName || tex.name || tex.id;
                return map;
            }, {});
        } catch (error) {
            console.warn('加载贴图列表失败:', error);
        }
        
        // 辅助函数：获取贴图显示名称
        const getTextureName = (textureType) => {
            // 先检查 textures 对象（新格式）
            if (mat.textures?.[textureType]?.name) {
                return mat.textures[textureType].name;
            }
            // 然后检查直接存储的贴图ID（旧格式）
            const textureId = mat[textureType];
            if (textureId && textureNameMap[textureId]) {
                return textureNameMap[textureId];
            }
            return '';
        };
        
        container.innerHTML = `
            <div class="material-params-header">
                <div class="material-params-actions-row">
                    <div class="material-unsaved-container">
                        <span class="material-unsaved-indicator" id="material-unsaved-indicator" style="display: none;">●</span>
                        <span class="material-unsaved-text" id="material-unsaved-text" style="display: none;">未保存</span>
                    </div>
                    <div class="material-params-actions-buttons">
                        <button class="btn-material-action preview" id="btn-toggle-preview">
                            <span>👁️</span>
                            <span>预览</span>
                        </button>
                        <button class="btn-material-action save" id="btn-save-material-top">
                            <span>💾</span>
                            <span>保存</span>
                        </button>
                        <button class="btn-material-action apply" id="btn-apply-to-mesh">应用到选中Mesh</button>
                        <button class="btn-material-action info" id="btn-show-usage">
                            <span>📊</span>
                            <span>引用</span>
                        </button>
                        <button class="btn-material-action" id="btn-duplicate-material">复制</button>
                    </div>
                </div>
            </div>
            
            <div class="material-params-scroll">
                <!-- 基础参数 -->
                <div class="material-param-group" data-group="basic">
                    <div class="param-group-title" data-group="basic">
                        <span class="param-group-icon">▼</span>
                        <span>基础参数</span>
                    </div>
                    <div class="param-group-content">
                        <div class="param-item">
                            <label>基础颜色</label>
                            <div class="param-input-row">
                                <input type="color" id="mat-color" value="${mat.color || '#ffffff'}" />
                                <input type="text" id="mat-color-hex" value="${mat.color || '#ffffff'}" 
                                       placeholder="#FFFFFF" class="param-input-hex" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>金属度 (Metalness)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-metalness" min="0" max="1" step="0.01" 
                                       value="${mat.metalness !== undefined ? mat.metalness : 0.5}" />
                                <input type="number" id="mat-metalness-value" min="0" max="1" step="0.01" 
                                       value="${mat.metalness !== undefined ? mat.metalness : 0.5}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>粗糙度 (Roughness)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-roughness" min="0" max="1" step="0.01" 
                                       value="${mat.roughness !== undefined ? mat.roughness : 0.5}" />
                                <input type="number" id="mat-roughness-value" min="0" max="1" step="0.01" 
                                       value="${mat.roughness !== undefined ? mat.roughness : 0.5}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>透明度 (Opacity)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-opacity" min="0" max="1" step="0.01" 
                                       value="${mat.opacity !== undefined ? mat.opacity : 1}" />
                                <input type="number" id="mat-opacity-value" min="0" max="1" step="0.01" 
                                       value="${mat.opacity !== undefined ? mat.opacity : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label class="param-checkbox-label">
                                <input type="checkbox" id="mat-double-sided" 
                                       ${mat.doubleSided ? 'checked' : ''} />
                                <span>双面渲染 (Double Sided)</span>
                            </label>
                            <div style="font-size: 11px; color: #999; margin-top: 4px; padding-left: 24px;">
                                开启后物体两面都会渲染，适用于树叶、窗帘等
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>自发光颜色</label>
                            <div class="param-input-row">
                                <input type="color" id="mat-emissive" value="${mat.emissive || '#000000'}" />
                                <input type="text" id="mat-emissive-hex" value="${mat.emissive || '#000000'}" 
                                       placeholder="#000000" class="param-input-hex" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>自发光强度</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-emissive-intensity" min="0" max="2" step="0.1" 
                                       value="${mat.emissiveIntensity !== undefined ? mat.emissiveIntensity : 0}" />
                                <input type="number" id="mat-emissive-intensity-value" min="0" max="2" step="0.1" 
                                       value="${mat.emissiveIntensity !== undefined ? mat.emissiveIntensity : 0}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- 纹理贴图 -->
                <div class="material-param-group" data-group="textures">
                    <div class="param-group-title" data-group="textures">
                        <span class="param-group-icon">▶</span>
                        <span>纹理贴图</span>
                    </div>
                    <div class="param-group-content collapsed">
                        <div class="param-item">
                            <label>基础颜色贴图 (Albedo/Diffuse)</label>
                            <div class="param-texture-row">
                                <input type="text" id="mat-map" value="${getTextureName('map')}" 
                                       placeholder="未选择贴图" class="param-input-texture" readonly />
                                <button class="btn-select-texture" data-texture-type="map">选择</button>
                                <button class="btn-clear-texture" data-texture-type="map">×</button>
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>基础颜色贴图强度</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-map-intensity" min="0" max="1" step="0.01" 
                                       value="${mat.mapIntensity !== undefined ? mat.mapIntensity : 1}" />
                                <input type="number" id="mat-map-intensity-value" min="0" max="1" step="0.01" 
                                       value="${mat.mapIntensity !== undefined ? mat.mapIntensity : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>法线贴图 (Normal Map)</label>
                            <div class="param-texture-row">
                                <input type="text" id="mat-normal-map" value="${getTextureName('normalMap')}" 
                                       placeholder="未选择贴图" class="param-input-texture" readonly />
                                <button class="btn-select-texture" data-texture-type="normalMap">选择</button>
                                <button class="btn-clear-texture" data-texture-type="normalMap">×</button>
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>法线贴图强度</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-normal-scale" min="0" max="2" step="0.1" 
                                       value="${mat.normalScale !== undefined ? (typeof mat.normalScale === 'object' ? (mat.normalScale.x || 1) : mat.normalScale) : 1}" />
                                <input type="number" id="mat-normal-scale-value" min="0" max="2" step="0.1" 
                                       value="${mat.normalScale !== undefined ? (typeof mat.normalScale === 'object' ? (mat.normalScale.x || 1) : mat.normalScale) : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>凹凸贴图 (Bump Map)</label>
                            <div class="param-texture-row">
                                <input type="text" id="mat-bump-map" value="${getTextureName('bumpMap')}" 
                                       placeholder="未选择贴图" class="param-input-texture" readonly />
                                <button class="btn-select-texture" data-texture-type="bumpMap">选择</button>
                                <button class="btn-clear-texture" data-texture-type="bumpMap">×</button>
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>凹凸强度</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-bump-scale" min="0" max="2" step="0.1" 
                                       value="${mat.bumpScale !== undefined ? mat.bumpScale : 0}" />
                                <input type="number" id="mat-bump-scale-value" min="0" max="2" step="0.1" 
                                       value="${mat.bumpScale !== undefined ? mat.bumpScale : 0}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>AO贴图 (Ambient Occlusion)</label>
                            <div class="param-texture-row">
                                <input type="text" id="mat-ao-map" value="${getTextureName('aoMap')}" 
                                       placeholder="未选择贴图" class="param-input-texture" readonly />
                                <button class="btn-select-texture" data-texture-type="aoMap">选择</button>
                                <button class="btn-clear-texture" data-texture-type="aoMap">×</button>
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>AO强度</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-ao-intensity" min="0" max="2" step="0.1" 
                                       value="${mat.aoIntensity !== undefined ? mat.aoIntensity : 1}" />
                                <input type="number" id="mat-ao-intensity-value" min="0" max="2" step="0.1" 
                                       value="${mat.aoIntensity !== undefined ? mat.aoIntensity : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>粗糙度贴图 (Roughness Map)</label>
                            <div class="param-texture-row">
                                <input type="text" id="mat-roughness-map" value="${getTextureName('roughnessMap')}" 
                                       placeholder="未选择贴图" class="param-input-texture" readonly />
                                <button class="btn-select-texture" data-texture-type="roughnessMap">选择</button>
                                <button class="btn-clear-texture" data-texture-type="roughnessMap">×</button>
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>粗糙度贴图强度</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-roughness-map-intensity" min="0" max="1" step="0.01" 
                                       value="${mat.roughnessMapIntensity !== undefined ? mat.roughnessMapIntensity : 1}" />
                                <input type="number" id="mat-roughness-map-intensity-value" min="0" max="1" step="0.01" 
                                       value="${mat.roughnessMapIntensity !== undefined ? mat.roughnessMapIntensity : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>金属度贴图 (Metalness Map)</label>
                            <div class="param-texture-row">
                                <input type="text" id="mat-metalness-map" value="${getTextureName('metalnessMap')}" 
                                       placeholder="未选择贴图" class="param-input-texture" readonly />
                                <button class="btn-select-texture" data-texture-type="metalnessMap">选择</button>
                                <button class="btn-clear-texture" data-texture-type="metalnessMap">×</button>
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>金属度贴图强度</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-metalness-map-intensity" min="0" max="1" step="0.01" 
                                       value="${mat.metalnessMapIntensity !== undefined ? mat.metalnessMapIntensity : 1}" />
                                <input type="number" id="mat-metalness-map-intensity-value" min="0" max="1" step="0.01" 
                                       value="${mat.metalnessMapIntensity !== undefined ? mat.metalnessMapIntensity : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- UV调整 -->
                <div class="material-param-group" data-group="uv">
                    <div class="param-group-title" data-group="uv">
                        <span class="param-group-icon">▶</span>
                        <span>UV调整</span>
                    </div>
                    <div class="param-group-content collapsed">
                        <div class="param-item">
                            <label>UV重复 - X (Repeat X)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-uv-repeat-x" min="0.1" max="10" step="0.1" 
                                       value="${mat.uvRepeatX !== undefined ? mat.uvRepeatX : 1}" />
                                <input type="number" id="mat-uv-repeat-x-value" min="0.1" max="10" step="0.1" 
                                       value="${mat.uvRepeatX !== undefined ? mat.uvRepeatX : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>UV重复 - Y (Repeat Y)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-uv-repeat-y" min="0.1" max="10" step="0.1" 
                                       value="${mat.uvRepeatY !== undefined ? mat.uvRepeatY : 1}" />
                                <input type="number" id="mat-uv-repeat-y-value" min="0.1" max="10" step="0.1" 
                                       value="${mat.uvRepeatY !== undefined ? mat.uvRepeatY : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>UV偏移 - X (Offset X)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-uv-offset-x" min="-2" max="2" step="0.01" 
                                       value="${mat.uvOffsetX !== undefined ? mat.uvOffsetX : 0}" />
                                <input type="number" id="mat-uv-offset-x-value" min="-2" max="2" step="0.01" 
                                       value="${mat.uvOffsetX !== undefined ? mat.uvOffsetX : 0}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>UV偏移 - Y (Offset Y)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-uv-offset-y" min="-2" max="2" step="0.01" 
                                       value="${mat.uvOffsetY !== undefined ? mat.uvOffsetY : 0}" />
                                <input type="number" id="mat-uv-offset-y-value" min="-2" max="2" step="0.01" 
                                       value="${mat.uvOffsetY !== undefined ? mat.uvOffsetY : 0}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>UV旋转 (Rotation)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-uv-rotation" min="0" max="6.28" step="0.01" 
                                       value="${mat.uvRotation !== undefined ? mat.uvRotation : 0}" />
                                <input type="number" id="mat-uv-rotation-value" min="0" max="360" step="1" 
                                       value="${mat.uvRotation !== undefined ? (mat.uvRotation * 180 / Math.PI).toFixed(0) : 0}" 
                                       class="param-input-number" 
                                       placeholder="角度" />
                                <span style="margin-left: 5px; font-size: 12px; color: #666;">°</span>
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>UV中心点 - X (Center X)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-uv-center-x" min="0" max="1" step="0.01" 
                                       value="${mat.uvCenterX !== undefined ? mat.uvCenterX : 0.5}" />
                                <input type="number" id="mat-uv-center-x-value" min="0" max="1" step="0.01" 
                                       value="${mat.uvCenterX !== undefined ? mat.uvCenterX : 0.5}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                        
                        <div class="param-item">
                            <label>UV中心点 - Y (Center Y)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-uv-center-y" min="0" max="1" step="0.01" 
                                       value="${mat.uvCenterY !== undefined ? mat.uvCenterY : 0.5}" />
                                <input type="number" id="mat-uv-center-y-value" min="0" max="1" step="0.01" 
                                       value="${mat.uvCenterY !== undefined ? mat.uvCenterY : 0.5}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- ✨ Z-Fighting 修复 -->
                <div class="material-param-group" data-group="zfighting">
                    <div class="param-group-title" data-group="zfighting">
                        <span class="param-group-icon">▶</span>
                        <span>✨ Z-Fighting 修复</span>
                    </div>
                    <div class="param-group-content collapsed">
                        <div class="param-item param-zfighting-section">
                            <label class="param-checkbox-label">
                                <input type="checkbox" id="mat-zfighting-enabled" 
                                       ${mat.polygonOffset ? 'checked' : ''} />
                                <span>启用多边形偏移</span>
                            </label>
                            <div style="font-size: 11px; color: #999; margin-top: 4px; padding-left: 24px;">
                                解决面重叠闪烁问题（Z-Fighting），适用于贴近表面或重叠面
                            </div>
                        </div>
                        
                        <div class="param-item param-zfighting-params" style="display: ${mat.polygonOffset ? 'block' : 'none'};">
                            <div class="param-help-mini" style="background: rgba(102, 126, 234, 0.08); padding: 10px; border-radius: 4px; margin-bottom: 12px;">
                                <div style="font-size: 11px; color: #667eea; margin-bottom: 6px;">💡 参数推荐值</div>
                                <div style="font-size: 10px; color: #999; line-height: 1.6;">
                                    • 轻微闪烁：1-2<br>
                                    • 中度闪烁：2-5 (推荐)<br>
                                    • 严重闪烁：5-10<br>
                                    • 贴花向前：负值 -1 至 -2
                                </div>
                            </div>
                            
                            <div style="margin-bottom: 12px; display: flex; gap: 4px;">
                                <button class="btn-zfighting-preset" data-value="1" onclick="window.materialEditorPanel.applyZFightingPreset(1)" style="flex: 1; padding: 6px 8px; font-size: 11px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 4px; cursor: pointer;">轻微(1)</button>
                                <button class="btn-zfighting-preset" data-value="2" onclick="window.materialEditorPanel.applyZFightingPreset(2)" style="flex: 1; padding: 6px 8px; font-size: 11px; background: rgba(102, 126, 234, 0.3); border: 1px solid rgba(102, 126, 234, 0.5); color: white; border-radius: 4px; cursor: pointer;">中度(2)</button>
                                <button class="btn-zfighting-preset" data-value="5" onclick="window.materialEditorPanel.applyZFightingPreset(5)" style="flex: 1; padding: 6px 8px; font-size: 11px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 4px; cursor: pointer;">高度(5)</button>
                                <button class="btn-zfighting-preset" data-value="-1" onclick="window.materialEditorPanel.applyZFightingPreset(-1)" style="flex: 1; padding: 6px 8px; font-size: 11px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 4px; cursor: pointer;">贴花(-1)</button>
                            </div>
                            
                            <label>偏移因子 (Factor)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-zfighting-factor" min="-10" max="10" step="0.5" 
                                       value="${mat.polygonOffsetFactor !== undefined ? mat.polygonOffsetFactor : 1}" />
                                <input type="number" id="mat-zfighting-factor-value" min="-10" max="10" step="0.5" 
                                       value="${mat.polygonOffsetFactor !== undefined ? mat.polygonOffsetFactor : 1}" 
                                       class="param-input-number" />
                            </div>
                            
                            <label style="margin-top: 8px;">偏移单位 (Units)</label>
                            <div class="param-input-row">
                                <input type="range" id="mat-zfighting-units" min="-10" max="10" step="0.5" 
                                       value="${mat.polygonOffsetUnits !== undefined ? mat.polygonOffsetUnits : 1}" />
                                <input type="number" id="mat-zfighting-units-value" min="-10" max="10" step="0.5" 
                                       value="${mat.polygonOffsetUnits !== undefined ? mat.polygonOffsetUnits : 1}" 
                                       class="param-input-number" />
                            </div>
                        </div>
                    </div>
                </div>
                
            </div>
        `;
        
        // 不在这里初始化预览，改为按需显示
        
        // 绑定参数编辑事件
        this.bindParamEvents();
        
        // 初始化默认状态到localStorage（确保有默认值）
        this.initializeDefaultStates();
        
        // 恢复折叠状态
        this.restoreParamGroupStates();
        
        // 绑定参数组折叠/展开事件
        this.bindParamGroupCollapseEvents();
    }
    
    /**
     * 绑定参数组折叠/展开事件
     */
    bindParamGroupCollapseEvents() {
        const titles = document.querySelectorAll('.param-group-title[data-group]');
        titles.forEach(title => {
            title.addEventListener('click', () => {
                const groupName = title.getAttribute('data-group');
                this.toggleParamGroup(groupName);
            });
            // 添加样式，让标题可点击
            title.style.cursor = 'pointer';
            title.style.userSelect = 'none';
        });
    }
    
    /**
     * 切换参数组的展开/折叠状态
     */
    toggleParamGroup(groupName) {
        const group = document.querySelector(`.material-param-group[data-group="${groupName}"]`);
        if (!group) return;
        
        const content = group.querySelector('.param-group-content');
        const icon = group.querySelector('.param-group-icon');
        
        if (!content || !icon) return;
        
        const isCollapsed = content.classList.contains('collapsed');
        
        if (isCollapsed) {
            // 展开
            content.classList.remove('collapsed');
            icon.textContent = '▼';
        } else {
            // 折叠
            content.classList.add('collapsed');
            icon.textContent = '▶';
        }
        
        // 保存状态
        this.saveParamGroupState(groupName, !isCollapsed);
    }
    
    /**
     * 保存参数组折叠状态到localStorage
     */
    saveParamGroupState(groupName, isCollapsed) {
        try {
            const key = 'materialEditor_paramGroupStates';
            const states = JSON.parse(localStorage.getItem(key) || '{}');
            states[groupName] = isCollapsed;
            localStorage.setItem(key, JSON.stringify(states));
        } catch (error) {
            console.error('保存参数组状态失败:', error);
        }
    }
    
    /**
     * 从localStorage恢复参数组折叠状态
     */
    restoreParamGroupStates() {
        try {
            const key = 'materialEditor_paramGroupStates';
            const savedStates = localStorage.getItem(key);
            
            if (!savedStates) {
                console.warn('⚠️ 没有保存的状态，应该先调用 initializeDefaultStates()');
                return;
            }
            
            const states = JSON.parse(savedStates);
            
            // 应用所有保存的状态
            Object.keys(states).forEach(groupName => {
                const isCollapsed = states[groupName];
                const group = document.querySelector(`.material-param-group[data-group="${groupName}"]`);
                if (group) {
                    const content = group.querySelector('.param-group-content');
                    const icon = group.querySelector('.param-group-icon');
                    if (content && icon) {
                        if (isCollapsed) {
                            content.classList.add('collapsed');
                            icon.textContent = '▶';
                        } else {
                            content.classList.remove('collapsed');
                            icon.textContent = '▼';
                        }
                    }
                }
            });
        } catch (error) {
            console.error('❌ 恢复参数组状态失败:', error);
        }
    }
    
    /**
     * 初始化默认状态到localStorage
     * 确保基础参数栏始终默认展开
     */
    initializeDefaultStates() {
        try {
            const key = 'materialEditor_paramGroupStates';
            const versionKey = 'materialEditor_paramGroupStates_version';
            const currentVersion = '1.1'; // 版本号，用于检测旧数据
            
            let states = {};
            let needsReset = false;
            
            const savedStates = localStorage.getItem(key);
            const savedVersion = localStorage.getItem(versionKey);
            
            // 检查版本，如果是旧版本或没有版本号，重置为默认状态
            if (savedVersion !== currentVersion) {
                needsReset = true;
            } else if (savedStates) {
                states = JSON.parse(savedStates);
            }
            
            // 设置默认状态：基础参数展开，其他收缩
            const defaultStates = {
                'basic': false,      // false = 展开
                'textures': true,    // true = 收缩
                'uv': true,
                'other': true
            };
            
            if (needsReset) {
                // 重置为默认状态
                states = { ...defaultStates };
            } else {
                // 合并：如果localStorage没有某个组的状态，使用默认值
                Object.keys(defaultStates).forEach(groupName => {
                    if (states[groupName] === undefined) {
                        states[groupName] = defaultStates[groupName];
                    }
                });
            }
            
            // 保存更新后的状态和版本号
            localStorage.setItem(key, JSON.stringify(states));
            localStorage.setItem(versionKey, currentVersion);
        } catch (error) {
            console.error('❌ 初始化默认状态失败:', error);
        }
    }
    
    /**
     * 创建预览浮动窗口
     */
    createPreviewFloatWindow() {
        // 检查是否已存在
        let floatWindow = document.getElementById('material-preview-float-window');
        if (floatWindow) return floatWindow;
        
        // 创建浮动窗口
        floatWindow = document.createElement('div');
        floatWindow.id = 'material-preview-float-window';
        floatWindow.className = 'material-preview-float-window';
        floatWindow.innerHTML = `
            <div class="preview-float-header" id="preview-float-header">
                <div class="preview-float-title">
                    <span>🎨</span>
                    <span>材质预览</span>
                </div>
                <div class="preview-float-actions">
                    <button class="preview-float-btn close" id="btn-close-preview-float" title="关闭">×</button>
                </div>
            </div>
            <div class="preview-float-content">
                <div id="material-preview-canvas-float" class="material-preview-canvas-float"></div>
                <button class="btn-reset-camera" id="btn-reset-camera-float">重置视角</button>
            </div>
        `;
        
        document.body.appendChild(floatWindow);
        
        // 绑定拖动事件
        this.bindFloatWindowDrag(floatWindow);
        
        // 绑定关闭按钮
        const btnClose = floatWindow.querySelector('#btn-close-preview-float');
        if (btnClose) {
            btnClose.addEventListener('click', () => this.hidePreviewWindow());
        }
        
        // 绑定重置相机按钮
        const btnResetCamera = floatWindow.querySelector('#btn-reset-camera-float');
        if (btnResetCamera) {
            btnResetCamera.addEventListener('click', () => this.resetCamera());
        }
        
        return floatWindow;
    }
    
    /**
     * 绑定浮动窗口拖动功能
     */
    bindFloatWindowDrag(floatWindow) {
        const header = floatWindow.querySelector('#preview-float-header');
        if (!header) return;
        
        let isDragging = false;
        let currentX, currentY, initialX, initialY;
        
        header.addEventListener('mousedown', (e) => {
            // 如果点击的是按钮，不触发拖动
            if (e.target.closest('.preview-float-btn')) return;
            
            isDragging = true;
            initialX = e.clientX - floatWindow.offsetLeft;
            initialY = e.clientY - floatWindow.offsetTop;
            
            header.style.cursor = 'grabbing';
        });
        
        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            
            e.preventDefault();
            currentX = e.clientX - initialX;
            currentY = e.clientY - initialY;
            
            floatWindow.style.left = currentX + 'px';
            floatWindow.style.top = currentY + 'px';
            floatWindow.style.right = 'auto';
        });
        
        document.addEventListener('mouseup', () => {
            if (isDragging) {
                isDragging = false;
                header.style.cursor = 'move';
            }
        });
    }
    
    /**
     * 显示预览窗口
     */
    showPreviewWindow() {
        const floatWindow = this.createPreviewFloatWindow();
        floatWindow.classList.add('visible');
        
        // 初始化预览
        this.initPreview();
    }
    
    /**
     * 隐藏预览窗口
     */
    hidePreviewWindow() {
        const floatWindow = document.getElementById('material-preview-float-window');
        if (floatWindow) {
            floatWindow.classList.remove('visible');
        }
        
        // 停止动画
        if (this.animationId) {
            cancelAnimationFrame(this.animationId);
            this.animationId = null;
        }
        
        // 清理渲染器和场景资源
        if (this.previewRenderer) {
            this.previewRenderer.dispose();
            this.previewRenderer = null;
        }
        if (this.previewScene) {
            this.previewScene = null;
        }
        if (this.previewCamera) {
            this.previewCamera = null;
        }
        if (this.previewMesh) {
            if (this.previewMesh.geometry) {
                this.previewMesh.geometry.dispose();
            }
            if (this.previewMesh.material) {
                this.previewMesh.material.dispose();
            }
            this.previewMesh = null;
        }
    }
    
    /**
     * 切换预览窗口显示/隐藏
     */
    togglePreviewWindow() {
        const floatWindow = document.getElementById('material-preview-float-window');
        if (floatWindow && floatWindow.classList.contains('visible')) {
            this.hidePreviewWindow();
        } else {
            this.showPreviewWindow();
        }
    }
    
    /**
     * 初始化预览
     */
    initPreview() {
        const container = document.getElementById('material-preview-canvas-float');
        if (!container || !this.selectedMaterialData) return;
        
        // 清除之前的预览
        if (this.animationId) {
            cancelAnimationFrame(this.animationId);
        }
        if (this.previewRenderer) {
            this.previewRenderer.dispose();
        }
        container.innerHTML = '';
        
        // 创建场景
        this.previewScene = new THREE.Scene();
        this.previewScene.background = new THREE.Color(0x1a1a1a);
        
        // 创建相机
        this.previewCamera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);
        this.previewCamera.position.set(0, 0, 5);
        
        // 创建渲染器
        this.previewRenderer = new THREE.WebGLRenderer({ antialias: true });
        this.previewRenderer.setSize(container.clientWidth, container.clientHeight);
        this.previewRenderer.setPixelRatio(window.devicePixelRatio);
        container.appendChild(this.previewRenderer.domElement);
        
        // 创建光照
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        this.previewScene.add(ambientLight);
        
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        directionalLight.position.set(5, 5, 5);
        this.previewScene.add(directionalLight);
        
        // 创建预览球体（异步加载纹理）
        const geometry = new THREE.SphereGeometry(1.5, 64, 64);
        this.createMaterialFromData(this.selectedMaterialData).then(material => {
            this.previewMesh = new THREE.Mesh(geometry, material);
            this.previewScene.add(this.previewMesh);
        });
        
        // 开始动画
        this.animate();
    }
    
    /**
     * 根据材质数据创建Three.js材质
     */
    async createMaterialFromData(data) {
        // 获取材质类型，默认为MeshStandardMaterial
        const MaterialClass = THREE[data.type] || THREE.MeshStandardMaterial;
        
        // 基础参数
        const baseParams = {
            color: new THREE.Color(data.color || '#ffffff'),
            opacity: data.opacity !== undefined ? data.opacity : 1,
            // 🔧 修复：透明相关参数 - 避免transparent和alphaTest冲突
            transparent: data.transparent !== undefined ? data.transparent : false,
            alphaTest: data.alphaTest !== undefined ? data.alphaTest : 0,
            depthWrite: data.depthWrite !== undefined ? data.depthWrite : true,
            depthTest: true,    // 保持深度测试
            side: data.doubleSided ? THREE.DoubleSide : THREE.FrontSide
        };
        
        // 根据材质类型添加特定参数
        if (data.type === 'MeshStandardMaterial' || data.type === 'MeshPhysicalMaterial') {
            baseParams.metalness = data.metalness !== undefined ? data.metalness : 0.5;
            baseParams.roughness = data.roughness !== undefined ? data.roughness : 0.5;
            baseParams.emissive = new THREE.Color(data.emissive || '#000000');
            baseParams.emissiveIntensity = data.emissiveIntensity !== undefined ? data.emissiveIntensity : 0;
        } else if (data.type === 'MeshPhongMaterial') {
            baseParams.shininess = data.shininess !== undefined ? data.shininess : 30;
            baseParams.emissive = new THREE.Color(data.emissive || '#000000');
            baseParams.specular = new THREE.Color(data.specular || '#111111');
        } else if (data.type === 'MeshLambertMaterial') {
            baseParams.emissive = new THREE.Color(data.emissive || '#000000');
        }
        // MeshBasicMaterial 只需要基础参数
        
        const material = new MaterialClass(baseParams);
        
        // 🎨 加载纹理
        await this.loadTexturesForMaterial(material, data);
        
        return material;
    }
    
    /**
     * 为材质加载纹理
     * @param {THREE.Material} material - 材质对象
     * @param {Object} data - 材质数据
     */
    async loadTexturesForMaterial(material, data) {
        const textureLoader = new THREE.TextureLoader();
        const backendUrl = 'http://localhost:7284';
        
        // 🔧 辅助函数：设置高质量纹理过滤（修复模糊问题）
        const applyTextureFilters = (texture) => {
            texture.generateMipmaps = true;  // 启用 mipmap 生成
            texture.minFilter = THREE.LinearMipmapLinearFilter;  // 缩小时使用三线性过滤
            texture.magFilter = THREE.LinearFilter;              // 放大时使用线性过滤
            const renderer = window.manager?.renderer;
            const maxAnisotropy = renderer ? renderer.capabilities.getMaxAnisotropy() : 16;
            texture.anisotropy = maxAnisotropy;  // 各向异性过滤（提升倾斜角度清晰度）
            texture.needsUpdate = true;  // 标记需要更新
        };
        
        // 辅助函数：通过纹理名称查找路径
        const getTexturePath = async (textureNameOrPath) => {
            if (!textureNameOrPath) return null;
            
            // 如果已经是路径，直接返回
            if (textureNameOrPath.startsWith('/')) {
                return textureNameOrPath;
            }
            
            // 通过API查找纹理
            try {
                const response = await fetch(`/api/projects/${this.projectId}/textures`);
                if (!response.ok) return null;
                
                const result = await response.json();
                if (!result.success || !result.data) return null;
                
                const texture = result.data.find(t => 
                    t.displayName === textureNameOrPath || 
                    t.name === textureNameOrPath ||
                    t.id === textureNameOrPath
                );
                
                if (texture && texture.id) {
                    // 使用正确的API路由：/api/projects/:id/textures/:textureId/file
                    return `/api/projects/${this.projectId}/textures/${texture.id}/file`;
                }
                
                console.warn(`⚠️ [预览纹理] 未找到纹理: ${textureNameOrPath}`);
                return null;
            } catch (error) {
                console.error('❌ [预览纹理] 查找纹理失败:', error);
                return null;
            }
        };
        
        // 辅助函数：应用UV变换
        const applyUVTransform = (texture) => {
            if (!texture) return;
            
            const uvRepeatX = data.uvRepeatX !== undefined ? data.uvRepeatX : 1;
            const uvRepeatY = data.uvRepeatY !== undefined ? data.uvRepeatY : 1;
            const uvOffsetX = data.uvOffsetX !== undefined ? data.uvOffsetX : 0;
            const uvOffsetY = data.uvOffsetY !== undefined ? data.uvOffsetY : 0;
            const uvRotation = data.uvRotation !== undefined ? data.uvRotation : 0;
            const uvCenterX = data.uvCenterX !== undefined ? data.uvCenterX : 0.5;
            const uvCenterY = data.uvCenterY !== undefined ? data.uvCenterY : 0.5;
            
            texture.repeat.set(uvRepeatX, uvRepeatY);
            texture.offset.set(uvOffsetX, uvOffsetY);
            texture.rotation = uvRotation;
            texture.center.set(uvCenterX, uvCenterY);
            texture.needsUpdate = true;
        };
        
        // 加载基础颜色贴图
        if (data.map) {
            const texturePath = await getTexturePath(data.map);
            if (texturePath) {
                console.log(`   📥 加载基础颜色贴图: ${texturePath}`);
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        console.log(`   ✅ 基础颜色贴图加载成功`);
                        texture.colorSpace = THREE.SRGBColorSpace;
                        applyTextureFilters(texture);  // 🔧 应用高质量过滤
                        applyUVTransform(texture);
                        material.map = texture;
                        
                        // 🔧 修复：PNG透明贴图支持 - 使用alphaTest实现像素级透明
                        // alphaTest：丢弃alpha值低于阈值的像素，这些像素不会写入深度缓冲
                        // 对于树叶等硬边透明（完全透明或完全不透明）效果更好
                        if (texturePath.toLowerCase().match(/\.(png|tga|webp)$/)) {
                            material.alphaTest = 0.5;      // alpha < 0.5 的像素被丢弃
                            material.transparent = true;   // 🔧 启用透明模式以正确排序
                            material.depthWrite = false;   // 🔧 禁用深度写入，避免双面自遮挡
                            material.depthTest = true;     // 保持深度测试
                            console.log(`   ✓ 检测到透明通道贴图，已启用alphaTest=0.5（硬边透明）`);
                        }
                        
                        // 应用贴图强度（保存到userData，后续通过shader或混合实现）
                        if (data.mapIntensity !== undefined) {
                            material.userData.mapIntensity = data.mapIntensity;
                        }
                        material.needsUpdate = true;
                    },
                    undefined,
                    (error) => console.error('   ❌ 加载基础颜色贴图失败:', error)
                );
            }
        }
        
        // 加载法线贴图
        if (data.normalMap) {
            const texturePath = await getTexturePath(data.normalMap);
            if (texturePath) {
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        applyTextureFilters(texture);  // 🔧 应用高质量过滤
                        applyUVTransform(texture);
                        material.normalMap = texture;
                        // 应用法线贴图强度
                        const normalScale = data.normalScale !== undefined ? data.normalScale : 1;
                        material.normalScale = new THREE.Vector2(normalScale, normalScale);
                        material.needsUpdate = true;
                    },
                    undefined,
                    (error) => console.warn('加载法线贴图失败:', error)
                );
            }
        }
        
        // 加载凹凸贴图
        if (data.bumpMap) {
            const texturePath = await getTexturePath(data.bumpMap);
            if (texturePath) {
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        applyTextureFilters(texture);  // 🔧 应用高质量过滤
                        applyUVTransform(texture);
                        material.bumpMap = texture;
                        material.bumpScale = data.bumpScale || 0;
                        material.needsUpdate = true;
                    },
                    undefined,
                    (error) => console.warn('加载凹凸贴图失败:', error)
                );
            }
        }
        
        // 加载AO贴图
        if (data.aoMap) {
            const texturePath = await getTexturePath(data.aoMap);
            if (texturePath) {
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        applyTextureFilters(texture);  // 🔧 应用高质量过滤
                        applyUVTransform(texture);
                        material.aoMap = texture;
                        material.aoMapIntensity = data.aoIntensity || 1;
                        material.needsUpdate = true;
                    },
                    undefined,
                    (error) => console.warn('加载AO贴图失败:', error)
                );
            }
        }
        
        // 加载粗糙度贴图
        if (data.roughnessMap) {
            const texturePath = await getTexturePath(data.roughnessMap);
            if (texturePath) {
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        applyTextureFilters(texture);  // 🔧 应用高质量过滤
                        applyUVTransform(texture);
                        material.roughnessMap = texture;
                        // 应用粗糙度贴图强度（保存到userData）
                        if (data.roughnessMapIntensity !== undefined) {
                            material.userData.roughnessMapIntensity = data.roughnessMapIntensity;
                        }
                        material.needsUpdate = true;
                    },
                    undefined,
                    (error) => console.warn('加载粗糙度贴图失败:', error)
                );
            }
        }
        
        // 加载金属度贴图
        if (data.metalnessMap) {
            const texturePath = await getTexturePath(data.metalnessMap);
            if (texturePath) {
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        applyTextureFilters(texture);  // 🔧 应用高质量过滤
                        applyUVTransform(texture);
                        material.metalnessMap = texture;
                        // 应用金属度贴图强度（保存到userData）
                        if (data.metalnessMapIntensity !== undefined) {
                            material.userData.metalnessMapIntensity = data.metalnessMapIntensity;
                        }
                        material.needsUpdate = true;
                    },
                    undefined,
                    (error) => console.warn('加载金属度贴图失败:', error)
                );
            }
        }
        
        // 🎯 加载透明贴图（alphaMap）- 关键修复！
        if (data.alphaMap) {
            console.log(`🎭 [贴图加载] 准备加载透明贴图: "${data.alphaMap}"`);
            const texturePath = await getTexturePath(data.alphaMap);
            if (texturePath) {
                const fullUrl = `${backendUrl}${texturePath}`;
                console.log(`   📥 开始加载透明贴图: ${fullUrl}`);
                textureLoader.load(
                    fullUrl,
                    (texture) => {
                        console.log(`   ✅ 透明贴图加载成功!`);
                        applyTextureFilters(texture);  // 🔧 应用高质量过滤
                        applyUVTransform(texture);
                        material.alphaMap = texture;
                        
                        // 🔧 关键设置：启用透明度
                        material.transparent = true;
                        
                        // 🔧 设置 alphaTest（如果配置中没有指定，使用默认值 0.5）
                        if (material.alphaTest === undefined || material.alphaTest === 0) {
                            material.alphaTest = 0.5;
                            console.log(`   ⚙️ 设置默认 alphaTest: 0.5`);
                        }
                        
                        // 🔧 关键：禁用深度写入，防止透明区域遮挡后面的物体
                        material.depthWrite = false;
                        material.depthTest = true;
                        console.log(`   ⚙️ 设置透明渲染参数: depthWrite=false, depthTest=true`);
                        
                        // 应用透明贴图强度（保存到userData）
                        if (data.alphaMapIntensity !== undefined) {
                            material.userData.alphaMapIntensity = data.alphaMapIntensity;
                        }
                        
                        material.needsUpdate = true;
                        console.log(`   ✅ 透明材质配置完成`);
                    },
                    undefined,
                    (error) => {
                        console.error('   ❌ 加载透明贴图失败:', error);
                        console.error('      - URL:', fullUrl);
                    }
                );
            } else {
                console.warn(`   ⚠️ 无法获取透明贴图路径，跳过加载`);
            }
        }
        
        // 🎨 贴图加载完成后，检查并修复暗色透明材质
        this.checkAndFixDarkTransparentMaterial(material, data);
    }
    
    /**
     * 检查并修复单个暗色透明材质（在贴图加载完成后调用）
     * @param {THREE.Material} material - 材质对象
     * @param {Object} materialData - 材质数据
     */
    checkAndFixDarkTransparentMaterial(material, materialData) {
        const matName = (materialData.displayName || materialData.name || '').toLowerCase();
        const isRoadLine = matName.includes('马路') || matName.includes('线') || 
                         matName.includes('road') || matName.includes('line');
        
        // 🎯 新策略：alpha值为透明则以alpha值为准做透明效果
        const hasAlphaTransparency = material.opacity < 1 || material.alphaTest > 0 || material.transparent;
        
        if (hasAlphaTransparency) {
            console.log(`🎨 [Alpha优先透明策略] 检测到alpha透明材质: ${materialData.displayName || materialData.name}`);
            console.log(`   Alpha设置: opacity=${material.opacity}, alphaTest=${material.alphaTest}, transparent=${material.transparent}`);
            
            // 🔑 关键策略：alpha值为透明时，降低贴图RGB和基础颜色的影响
            if (material.opacity < 1) {
                // opacity透明模式：以opacity值为准
                material.transparent = true;
                material.alphaTest = 0;
                material.depthWrite = false;
                material.depthTest = true;
                
                // 🎯 降低贴图RGB通道影响：将基础颜色调亮，让透明区域更纯净
                if (material.map) {
                    // 有贴图时：基础颜色设为白色或浅色，让贴图的alpha通道主导透明效果
                    material.color.setRGB(1.0, 1.0, 1.0); // 白色基础，不干扰贴图alpha
                    console.log(`   🔧 opacity透明模式：基础颜色设为白色，贴图alpha通道主导`);
                } else {
                    // 无贴图时：保持基础颜色，但确保透明效果正确
                    console.log(`   🔧 opacity透明模式：保持基础颜色，opacity=${material.opacity}`);
                }
                
            } else if (material.alphaTest > 0) {
                // alphaTest透明模式：硬边透明
                material.transparent = false;
                material.depthWrite = true;
                material.depthTest = true;
                
                if (material.map) {
                    // 有贴图时：基础颜色设为白色，让贴图的alpha通道决定透明边界
                    material.color.setRGB(1.0, 1.0, 1.0);
                    console.log(`   🔧 alphaTest透明模式：基础颜色设为白色，alphaTest=${material.alphaTest}`);
                } else {
                    // 无贴图时：alphaTest对纯色材质无效，转为opacity模式
                    material.transparent = true;
                    material.alphaTest = 0;
                    material.depthWrite = false;
                    material.opacity = 0.8; // 设置合理的透明度
                    console.log(`   🔧 无贴图alphaTest转opacity模式：opacity=${material.opacity}`);
                }
                
            } else if (material.transparent) {
                // 纯transparent模式
                material.alphaTest = 0;
                material.depthWrite = false;
                material.depthTest = true;
                
                if (material.map) {
                    // 有贴图时：基础颜色设为白色
                    material.color.setRGB(1.0, 1.0, 1.0);
                    console.log(`   🔧 transparent模式：基础颜色设为白色`);
                }
            }
            
            // 🎯 特殊处理：马路线等贴地透明物体
            if (isRoadLine) {
                material.transparent = false;
                material.alphaTest = Math.max(0.1, material.alphaTest || 0.5);
                material.depthWrite = true;
                material.renderOrder = 100; // 贴地透明物体优先级
                
                if (material.map) {
                    material.color.setRGB(1.0, 1.0, 1.0); // 白色基础，让贴图主导
                }
                console.log(`   🛣️ 马路线特殊处理：alphaTest=${material.alphaTest}, renderOrder=100`);
            }
            
            material.needsUpdate = true;
            console.log(`   ✅ Alpha优先透明策略应用完成`);
            console.log(`   💡 原理：alpha值主导透明效果，贴图RGB和基础颜色影响降低`);
            
        } else {
            // 🎯 非透明材质：保持原有逻辑
            console.log(`🎨 [非透明材质] ${materialData.displayName || materialData.name}: 保持不透明状态`);
            material.transparent = false;
            material.alphaTest = 0;
            material.depthWrite = true;
            material.opacity = 1.0;
        }
    }
    
    /**
     * 动画循环
     */
    animate() {
        // ✅ 性能优化：检查预览窗口是否可见
        const floatWindow = document.getElementById('material-preview-float-window');
        const isVisible = floatWindow && floatWindow.classList.contains('visible');
        
        // 如果窗口不可见，停止动画循环
        if (!isVisible) {
            if (this.animationId) {
                cancelAnimationFrame(this.animationId);
                this.animationId = null;
            }
            return;
        }
        
        // 继续动画循环
        this.animationId = requestAnimationFrame(() => this.animate());
        
        if (this.previewMesh) {
            this.previewMesh.rotation.y += 0.005;
        }
        
        if (this.previewRenderer && this.previewScene && this.previewCamera) {
            this.previewRenderer.render(this.previewScene, this.previewCamera);
        }
    }
    
    /**
     * 绑定事件
     */
    bindEvents() {
        // 新建材质按钮
        const btnNewMaterial = document.getElementById('btn-new-material');
        if (btnNewMaterial) {
            btnNewMaterial.addEventListener('click', () => this.createNewMaterial());
        }
        
        // 搜索框
        const searchInput = document.getElementById('material-search-input');
        if (searchInput) {
            searchInput.addEventListener('input', (e) => {
                this.renderMaterialList(e.target.value);
            });
        }
        
        // 筛选勾选框 - 只显示当前场景使用的
        const filterCurrentSceneCheckbox = document.getElementById('material-filter-current-scene');
        if (filterCurrentSceneCheckbox) {
            filterCurrentSceneCheckbox.addEventListener('change', () => {
                this.renderMaterialList(searchInput ? searchInput.value : '');
            });
        }
        
        // 新建材质模态框事件
        const confirmBtn = document.getElementById('confirm-create-material');
        if (confirmBtn) {
            confirmBtn.addEventListener('click', () => this.confirmCreateMaterial());
        }
        
        const cancelBtn = document.getElementById('cancel-create-material');
        if (cancelBtn) {
            cancelBtn.addEventListener('click', () => this.closeCreateMaterialModal());
        }
        
        const closeBtn = document.getElementById('close-create-material-modal');
        if (closeBtn) {
            closeBtn.addEventListener('click', () => this.closeCreateMaterialModal());
        }
        
        // 点击模态框背景关闭
        const modal = document.getElementById('create-material-modal');
        if (modal) {
            modal.addEventListener('click', (e) => {
                if (e.target === modal) {
                    this.closeCreateMaterialModal();
                }
            });
        }
        
        // 回车键提交
        const nameInput = document.getElementById('new-material-display-name');
        if (nameInput) {
            nameInput.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    this.confirmCreateMaterial();
                }
            });
        }
        
        // 复制材质模态框事件
        const confirmDuplicateBtn = document.getElementById('confirm-duplicate-material');
        if (confirmDuplicateBtn) {
            confirmDuplicateBtn.addEventListener('click', () => this.confirmDuplicateMaterial());
        }
        
        const cancelDuplicateBtn = document.getElementById('cancel-duplicate-material');
        if (cancelDuplicateBtn) {
            cancelDuplicateBtn.addEventListener('click', () => this.closeDuplicateMaterialModal());
        }
        
        const closeDuplicateBtn = document.getElementById('close-duplicate-material-modal');
        if (closeDuplicateBtn) {
            closeDuplicateBtn.addEventListener('click', () => this.closeDuplicateMaterialModal());
        }
        
        // 点击模态框背景关闭
        const duplicateModal = document.getElementById('duplicate-material-modal');
        if (duplicateModal) {
            duplicateModal.addEventListener('click', (e) => {
                if (e.target === duplicateModal) {
                    this.closeDuplicateMaterialModal();
                }
            });
        }
        
        // 回车键提交
        const duplicateNameInput = document.getElementById('duplicate-material-display-name');
        if (duplicateNameInput) {
            duplicateNameInput.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    this.confirmDuplicateMaterial();
                }
            });
        }
    }
    
    /**
     * 绑定参数编辑事件
     */
    bindParamEvents() {
        // 同步滑块和数字输入
        this.syncRangeAndNumber('mat-metalness', 'mat-metalness-value');
        this.syncRangeAndNumber('mat-roughness', 'mat-roughness-value');
        this.syncRangeAndNumber('mat-opacity', 'mat-opacity-value');
        this.syncRangeAndNumber('mat-emissive-intensity', 'mat-emissive-intensity-value');
        this.syncRangeAndNumber('mat-bump-scale', 'mat-bump-scale-value');
        this.syncRangeAndNumber('mat-ao-intensity', 'mat-ao-intensity-value');
        
        // 贴图强度控件同步
        this.syncRangeAndNumber('mat-map-intensity', 'mat-map-intensity-value');
        this.syncRangeAndNumber('mat-normal-scale', 'mat-normal-scale-value');
        this.syncRangeAndNumber('mat-roughness-map-intensity', 'mat-roughness-map-intensity-value');
        this.syncRangeAndNumber('mat-metalness-map-intensity', 'mat-metalness-map-intensity-value');
        
        // UV调整参数同步
        this.syncRangeAndNumber('mat-uv-repeat-x', 'mat-uv-repeat-x-value');
        this.syncRangeAndNumber('mat-uv-repeat-y', 'mat-uv-repeat-y-value');
        this.syncRangeAndNumber('mat-uv-offset-x', 'mat-uv-offset-x-value');
        this.syncRangeAndNumber('mat-uv-offset-y', 'mat-uv-offset-y-value');
        this.syncRangeAndNumber('mat-uv-center-x', 'mat-uv-center-x-value');
        this.syncRangeAndNumber('mat-uv-center-y', 'mat-uv-center-y-value');
        
        // UV旋转特殊处理：滑块用弧度，数字输入用角度
        this.syncUVRotation();
        
        // Z-Fighting 参数同步
        this.syncRangeAndNumber('mat-zfighting-factor', 'mat-zfighting-factor-value');
        this.syncRangeAndNumber('mat-zfighting-units', 'mat-zfighting-units-value');
        
        // Z-Fighting 启用开关
        const zfightingEnabled = document.getElementById('mat-zfighting-enabled');
        if (zfightingEnabled) {
            zfightingEnabled.addEventListener('change', () => {
                this.toggleZFightingParams();
            });
        }
        
        // 同步颜色选择器和HEX输入
        this.syncColorAndHex('mat-color', 'mat-color-hex');
        this.syncColorAndHex('mat-emissive', 'mat-emissive-hex');
        
        // 保存按钮（标题栏）
        const btnSaveTop = document.getElementById('btn-save-material-top');
        if (btnSaveTop) {
            btnSaveTop.addEventListener('click', () => this.saveMaterial());
        }
        
        // 复制按钮
        const btnDuplicate = document.getElementById('btn-duplicate-material');
        if (btnDuplicate) {
            btnDuplicate.addEventListener('click', () => this.duplicateMaterial());
        }
        
        // 应用到选中Mesh按钮
        const btnApplyToMesh = document.getElementById('btn-apply-to-mesh');
        if (btnApplyToMesh) {
            btnApplyToMesh.addEventListener('click', () => this.applyMaterialToSelectedMesh());
        }
        
        // ⭐ 查看使用情况按钮
        const btnShowUsage = document.getElementById('btn-show-usage');
        if (btnShowUsage) {
            btnShowUsage.addEventListener('click', async () => await this.showMaterialUsage());
        }
        
        // 预览按钮
        const btnTogglePreview = document.getElementById('btn-toggle-preview');
        if (btnTogglePreview) {
            btnTogglePreview.addEventListener('click', () => this.togglePreviewWindow());
        }
        
        // 选择纹理按钮
        document.querySelectorAll('.btn-select-texture').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const textureType = e.target.dataset.textureType;
                this.selectTexture(textureType);
            });
        });
        
        // 清除纹理按钮
        document.querySelectorAll('.btn-clear-texture').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const textureType = e.target.dataset.textureType;
                this.clearTexture(textureType);
            });
        });
        
        // 实时更新预览
        this.bindPreviewUpdateEvents();
    }
    
    /**
     * 选择纹理（打开贴图选择对话框）
     */
    async selectTexture(textureType) {
        // 打开贴图选择对话框
        await this.showTextureSelectDialog(textureType);
    }
    
    /**
     * 显示贴图选择对话框
     */
    async showTextureSelectDialog(textureType) {
        try {
            // 加载项目中的所有贴图
            const textures = await this.loadProjectTextures();
            
            // 获取当前材质已有的贴图ID（支持新旧两种格式）
            const currentTextureId = this.selectedMaterialData?.textures?.[textureType]?.id 
                                   || this.selectedMaterialData?.[textureType] 
                                   || null;
            
            // 创建对话框
            const dialog = document.createElement('div');
            dialog.className = 'texture-select-dialog';
            
            dialog.innerHTML = `
                <div class="texture-select-dialog-content">
                    <div class="texture-select-dialog-header">
                        <h3>🖼️ 选择贴图</h3>
                        <button class="close-btn">✕</button>
                    </div>
                    <div class="texture-select-dialog-search">
                        <input type="text" placeholder="搜索贴图..." id="texture-search-input">
                    </div>
                    <div class="texture-select-dialog-body" id="texture-select-body">
                        ${textures.length === 0 ? this.renderEmptyTextureState() : this.renderTextureGrid(textures, currentTextureId)}
                    </div>
                    <div class="texture-select-dialog-footer">
                        <div class="texture-select-dialog-footer-left">
                            <button class="texture-select-upload-btn" id="btn-upload-new-texture">
                                ⬆️ 上传新贴图
                            </button>
                        </div>
                        <div class="texture-select-dialog-footer-right">
                            <button class="texture-select-cancel-btn" id="btn-cancel-select">取消</button>
                            <button class="texture-select-confirm-btn" id="btn-confirm-select" ${currentTextureId ? '' : 'disabled'}>确定</button>
                        </div>
                    </div>
                </div>
            `;
            
            document.body.appendChild(dialog);
            
            // 存储当前选中的贴图（如果已有贴图，默认选中）
            let selectedTexture = currentTextureId ? textures.find(t => t.id === currentTextureId) : null;
            
            // 搜索功能
            const searchInput = dialog.querySelector('#texture-search-input');
            searchInput.addEventListener('input', (e) => {
                const keyword = e.target.value.toLowerCase();
                const filteredTextures = textures.filter(tex => 
                    (tex.displayName || tex.name || '').toLowerCase().includes(keyword)
                );
                
                const body = dialog.querySelector('#texture-select-body');
                body.innerHTML = filteredTextures.length === 0 
                    ? this.renderEmptyTextureState('未找到匹配的贴图') 
                    : this.renderTextureGrid(filteredTextures, currentTextureId);
                
                // 重新绑定点击事件
                this.bindTextureItemClickEvents(dialog, (texture) => {
                    selectedTexture = texture;
                    dialog.querySelector('#btn-confirm-select').disabled = false;
                });
            });
            
            // 绑定贴图项点击事件
            this.bindTextureItemClickEvents(dialog, (texture) => {
                selectedTexture = texture;
                dialog.querySelector('#btn-confirm-select').disabled = false;
            });
            
            // 统一的关闭对话框函数（清空搜索框）
            const closeDialog = () => {
                // 清空搜索框
                if (searchInput) {
                    searchInput.value = '';
                }
                // 移除对话框
                dialog.remove();
                // 移除ESC键监听
                document.removeEventListener('keydown', handleEsc);
            };
            
            // 上传新贴图按钮
            dialog.querySelector('#btn-upload-new-texture').addEventListener('click', () => {
                closeDialog();
                this.uploadNewTexture(textureType);
            });
            
            // 取消按钮
            dialog.querySelector('#btn-cancel-select').addEventListener('click', () => {
                closeDialog();
            });
            
            // 确定按钮
            dialog.querySelector('#btn-confirm-select').addEventListener('click', async () => {
                if (selectedTexture) {
                    await this.applySelectedTexture(textureType, selectedTexture);
                    closeDialog();
                }
            });
            
            // 关闭按钮
            dialog.querySelector('.close-btn').addEventListener('click', () => {
                closeDialog();
            });
            
            // 点击背景关闭
            dialog.addEventListener('click', (e) => {
                if (e.target === dialog) {
                    closeDialog();
                }
            });
            
            // ESC键关闭
            const handleEsc = (e) => {
                if (e.key === 'Escape') {
                    closeDialog();
                }
            };
            document.addEventListener('keydown', handleEsc);
            
        } catch (error) {
            console.error('❌ 打开贴图选择对话框失败:', error);
            if (window.showManageMessage) {
                window.showManageMessage('加载贴图列表失败: ' + error.message, 'error');
            }
        }
    }
    
    /**
     * 加载项目中的所有贴图
     */
    async loadProjectTextures() {
        try {
            const response = await fetch(`/api/projects/${this.projectId}/textures`);
            const result = await response.json();
            
            if (result.success) {
                return result.data || [];
            } else {
                throw new Error(result.error || '加载失败');
            }
        } catch (error) {
            console.error('❌ 加载项目贴图失败:', error);
            return [];
        }
    }
    
    /**
     * 渲染贴图网格
     */
    renderTextureGrid(textures, currentTextureId = null) {
        if (textures.length === 0) {
            return this.renderEmptyTextureState();
        }
        
        const backendUrl = window.APP_CONFIG?.backendUrl || window.location.origin;
        
        const items = textures.map(texture => {
            const size = this.formatFileSize(texture.size);
            const displayName = texture.displayName || texture.name || '未命名';
            // 构造正确的贴图URL
            const textureUrl = `${backendUrl}/api/projects/${this.projectId}/textures/${texture.id}/file`;
            // 检查是否是当前已选中的贴图
            const isSelected = currentTextureId && texture.id === currentTextureId;
            
            return `
                <div class="texture-select-item ${isSelected ? 'selected' : ''}" data-texture-id="${texture.id}">
                    <div class="texture-select-item-preview">
                        <img src="${textureUrl}" alt="${displayName}" loading="lazy">
                    </div>
                    <div class="texture-select-item-info">
                        <div class="texture-select-item-name" title="${displayName}">${displayName}</div>
                        <div class="texture-select-item-size">${size}</div>
                    </div>
                    <div class="texture-select-item-badge">✓</div>
                </div>
            `;
        }).join('');
        
        return `<div class="texture-select-grid">${items}</div>`;
    }
    
    /**
     * 渲染空状态
     */
    renderEmptyTextureState(message = '暂无贴图') {
        return `
            <div class="texture-select-empty">
                <div class="texture-select-empty-icon">🖼️</div>
                <div class="texture-select-empty-text">${message}</div>
                <div class="texture-select-empty-hint">点击下方"上传新贴图"按钮添加</div>
            </div>
        `;
    }
    
    /**
     * 绑定贴图项点击事件
     */
    bindTextureItemClickEvents(dialog, onSelect) {
        const items = dialog.querySelectorAll('.texture-select-item');
        const allTextures = [];
        
        // 从DOM中获取贴图数据
        items.forEach(item => {
            const textureId = item.dataset.textureId;
            const img = item.querySelector('img');
            const name = item.querySelector('.texture-select-item-name').textContent;
            
            allTextures.push({
                id: textureId,
                url: img.src,
                displayName: name,
                element: item
            });
        });
        
        items.forEach((item, index) => {
            item.addEventListener('click', () => {
                // 移除其他项的选中状态
                items.forEach(i => i.classList.remove('selected'));
                // 添加当前项的选中状态
                item.classList.add('selected');
                // 回调
                if (onSelect) {
                    onSelect(allTextures[index]);
                }
            });
        });
    }
    
    /**
     * 应用选中的贴图
     */
    async applySelectedTexture(textureType, texture) {
        try {
            if (window.showManageMessage) {
                window.showManageMessage('正在应用贴图...', 'info');
            }
            
            // 更新材质数据中的贴图引用
            if (!this.selectedMaterialData.textures) {
                this.selectedMaterialData.textures = {};
            }
            
            // 保存贴图信息（新格式）
            this.selectedMaterialData.textures[textureType] = {
                id: texture.id,
                url: texture.url,
                name: texture.displayName || texture.name
            };
            
            // 同时更新旧格式（直接存储ID），保持兼容性
            this.selectedMaterialData[textureType] = texture.id;
            
            // 更新输入框显示
            const textureInput = this.getTextureInputElement(textureType);
            if (textureInput) {
                textureInput.value = texture.displayName || texture.name;
            }
            
            // 增加贴图引用计数（使用材质的displayName）
            const materialDisplayName = this.selectedMaterialData.displayName || this.selectedMaterialData.name;
            await this.addTextureReference(texture.id, materialDisplayName);
            
            // ⭐ 立即加载贴图并应用到场景中的模型
            await this.loadAndApplyTextureToScene(textureType, texture);
            
            // 更新预览
            this.updatePreview();
            
            // 标记为未保存
            this.markAsUnsaved();
            
            if (window.showManageMessage) {
                window.showManageMessage(`贴图 "${texture.displayName || texture.name}" 应用成功`, 'success');
            }
        } catch (error) {
            console.error('❌ 应用贴图失败:', error);
            if (window.showManageMessage) {
                window.showManageMessage('应用贴图失败: ' + error.message, 'error');
            }
        }
    }
    
    /**
     * 上传新贴图
     */
    uploadNewTexture(textureType) {
        // 创建文件输入
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = 'image/*';
        
        input.onchange = async (e) => {
            const file = e.target.files[0];
            if (!file) return;
            
            try {
                // 显示上传中状态
                if (window.showManageMessage) {
                    window.showManageMessage('正在上传贴图...', 'info');
                }
                
                // 上传贴图到服务器
                const uploadedTexture = await this.uploadTextureFile(file);
                
                // 应用上传的贴图
                await this.applySelectedTexture(textureType, uploadedTexture);
                
            } catch (error) {
                console.error('❌ 上传贴图失败:', error);
                if (window.showManageMessage) {
                    window.showManageMessage('上传贴图失败: ' + error.message, 'error');
                } else {
                    alert('上传贴图失败: ' + error.message);
                }
            }
        };
        
        input.click();
    }
    
    /**
     * 格式化文件大小
     */
    formatFileSize(bytes) {
        if (!bytes) return '0 B';
        
        const units = ['B', 'KB', 'MB', 'GB'];
        let size = bytes;
        let unitIndex = 0;
        
        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }
        
        return `${size.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;
    }
    
    /**
     * 上传贴图文件到服务器
     * @param {File} file - 贴图文件
     * @returns {Promise<Object>} 上传后的贴图信息
     */
    async uploadTextureFile(file) {
        const formData = new FormData();
        formData.append('texture', file);
        
        // ⭐ 关键：在FormData中传递正确的原始文件名，避免浏览器编码问题
        formData.append('originalFileName', file.name);
        
        const response = await fetch(`/api/projects/${this.projectId}/textures/upload`, {
            method: 'POST',
            body: formData
        });
        
        if (!response.ok) {
            const errorData = await response.json();
            throw new Error(errorData.error || '上传失败');
        }
        
        const result = await response.json();
        if (!result.success) {
            throw new Error(result.error || '上传失败');
        }
        
        console.log('✅ 贴图上传成功:', result.data);
        return result.data;
    }
    
    /**
     * 增加贴图引用计数
     * @param {string} textureId - 贴图ID
     * @param {string} materialDisplayName - 材质显示名称（displayName或name）
     */
    async addTextureReference(textureId, materialDisplayName) {
        try {
            console.log('🔍 增加贴图引用:', { textureId, materialDisplayName, projectId: this.projectId });
            
            if (!materialDisplayName) {
                console.error('❌ materialDisplayName 为空，无法增加引用');
                return;
            }
            
            const response = await fetch(`/api/projects/${this.projectId}/textures/${textureId}/add-reference`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ materialId: materialDisplayName })
            });
            
            if (!response.ok) {
                const errorData = await response.json().catch(() => ({}));
                console.warn('⚠️ 增加贴图引用计数失败:', errorData);
            }
        } catch (error) {
            console.warn('⚠️ 增加贴图引用计数失败:', error);
        }
    }
    
    /**
     * 减少贴图引用计数
     * @param {string} textureId - 贴图ID
     * @param {string} materialDisplayName - 材质显示名称（displayName或name）
     */
    async removeTextureReference(textureId, materialDisplayName) {
        try {
            console.log('🔍 减少贴图引用:', { textureId, materialDisplayName, projectId: this.projectId });
            
            if (!materialDisplayName) {
                console.error('❌ materialDisplayName 为空，无法减少引用');
                return;
            }
            
            const response = await fetch(`/api/projects/${this.projectId}/textures/${textureId}/remove-reference`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ materialId: materialDisplayName })
            });
            
            if (!response.ok) {
                const errorData = await response.json().catch(() => ({}));
                console.warn('⚠️ 减少贴图引用计数失败:', errorData);
            }
        } catch (error) {
            console.warn('⚠️ 减少贴图引用计数失败:', error);
        }
    }
    
    /**
     * 获取贴图输入元素
     */
    getTextureInputElement(textureType) {
        const idMap = {
            'map': 'mat-map',
            'normalMap': 'mat-normal-map',
            'bumpMap': 'mat-bump-map',
            'aoMap': 'mat-ao-map',
            'roughnessMap': 'mat-roughness-map',
            'metalnessMap': 'mat-metalness-map'
        };
        
        const inputId = idMap[textureType];
        return inputId ? document.getElementById(inputId) : null;
    }
    
    /**
     * 绑定预览更新事件
     */
    bindPreviewUpdateEvents() {
        const updatePreview = () => {
            this.updatePreview();
            this.markAsUnsaved(); // 标记为未保存
        };
        
        // 基础参数变化时更新预览
        ['mat-color', 'mat-metalness', 'mat-roughness', 'mat-opacity',
         'mat-emissive', 'mat-emissive-intensity', 'mat-double-sided',
         'mat-bump-scale', 'mat-ao-intensity',
         'mat-map-intensity', 'mat-normal-scale', 
         'mat-roughness-map-intensity', 'mat-metalness-map-intensity'].forEach(id => {
            const el = document.getElementById(id);
            if (el) {
                el.addEventListener('input', updatePreview);
                el.addEventListener('change', updatePreview);
            }
        });
        
        // UV调整参数变化时更新预览
        ['mat-uv-repeat-x', 'mat-uv-repeat-y', 'mat-uv-offset-x', 'mat-uv-offset-y',
         'mat-uv-rotation', 'mat-uv-center-x', 'mat-uv-center-y'].forEach(id => {
            const el = document.getElementById(id);
            if (el) {
                el.addEventListener('input', updatePreview);
                el.addEventListener('change', updatePreview);
            }
        });
        
        // HEX输入框变化
        ['mat-color-hex', 'mat-emissive-hex'].forEach(id => {
            const el = document.getElementById(id);
            if (el) {
                el.addEventListener('input', updatePreview);
            }
        });
    }
    
    /**
     * 标记材质为未保存
     */
    markAsUnsaved() {
        this.hasUnsavedChanges = true;
        const indicator = document.getElementById('material-unsaved-indicator');
        const text = document.getElementById('material-unsaved-text');
        if (indicator) {
            indicator.style.display = 'inline-block';
            indicator.title = '有未保存的修改';
        }
        if (text) {
            text.style.display = 'inline-block';
        }
    }
    
    /**
     * 标记材质为已保存
     */
    markAsSaved() {
        this.hasUnsavedChanges = false;
        const indicator = document.getElementById('material-unsaved-indicator');
        const text = document.getElementById('material-unsaved-text');
        if (indicator) {
            indicator.style.display = 'none';
        }
        if (text) {
            text.style.display = 'none';
        }
    }
    
    /**
     * 检查是否有未保存的修改
     */
    checkUnsavedChanges() {
        if (this.hasUnsavedChanges) {
            // 显示自定义提示
            if (window.showManageMessage) {
                window.showManageMessage('材质有未保存的修改，请先保存！', 'warning');
            }
            return true;
        }
        return false;
    }
    
    /**
     * 更新预览（同时同步到场景中使用该材质的mesh）
     */
    updatePreview() {
        // ⭐ 先同步UI参数到selectedMaterialData（关键修复！）
        this.syncUIToMaterialData();
        
        // 只有当预览窗口打开时才更新预览
        const floatWindow = document.getElementById('material-preview-float-window');
        const isPreviewVisible = floatWindow && floatWindow.classList.contains('visible');
        
        if (isPreviewVisible && this.previewMesh && this.previewMesh.material) {
            const material = this.previewMesh.material;
            
            // 更新材质参数
            const colorInput = document.getElementById('mat-color');
            if (colorInput) {
                material.color.set(colorInput.value);
            }
            
            const metalnessInput = document.getElementById('mat-metalness');
            if (metalnessInput) {
                material.metalness = parseFloat(metalnessInput.value);
            }
            
            const roughnessInput = document.getElementById('mat-roughness');
            if (roughnessInput) {
                material.roughness = parseFloat(roughnessInput.value);
            }
            
            const opacityInput = document.getElementById('mat-opacity');
            if (opacityInput) {
                material.opacity = parseFloat(opacityInput.value);
                // 🔧 修复：如果有贴图或opacity<1，都需要开启transparent
                material.transparent = material.opacity < 1 || !!material.map || !!material.alphaMap;
            }
            
            const emissiveInput = document.getElementById('mat-emissive');
            if (emissiveInput) {
                material.emissive.set(emissiveInput.value);
            }
            
            const emissiveIntensityInput = document.getElementById('mat-emissive-intensity');
            if (emissiveIntensityInput) {
                material.emissiveIntensity = parseFloat(emissiveIntensityInput.value);
            }
            
            const doubleSidedInput = document.getElementById('mat-double-sided');
            if (doubleSidedInput) {
                material.side = doubleSidedInput.checked ? THREE.DoubleSide : THREE.FrontSide;
            }
            
            // 🎨 Z-Fighting 修复设置
            const zfightingEnabled = document.getElementById('mat-zfighting-enabled');
            if (zfightingEnabled) {
                material.polygonOffset = zfightingEnabled.checked;
                if (zfightingEnabled.checked) {
                    const factorInput = document.getElementById('mat-zfighting-factor');
                    const unitsInput = document.getElementById('mat-zfighting-units');
                    material.polygonOffsetFactor = factorInput ? parseFloat(factorInput.value) : 1;
                    material.polygonOffsetUnits = unitsInput ? parseFloat(unitsInput.value) : 1;
                } else {
                    material.polygonOffsetFactor = 0;
                    material.polygonOffsetUnits = 0;
                }
            }
            
            // 🔧 修复：根据不同情况使用不同的透明策略
            if (material.map || material.alphaMap || material.opacity < 1) {
                // 透明材质（包括贴图和半透明）
                if (material.map || material.alphaMap) {
                    // 有贴图：使用alphaTest进行像素级裁剪
                    material.alphaTest = 0.5;
                } else {
                    material.alphaTest = 0;
                }
                // 统一启用透明模式，避免双面自遮挡
                material.transparent = true;
                material.depthWrite = false;
                material.depthTest = true;
            }
            
            // 🎨 更新UV变换
            this.applyUVTransformToMaterial(material);
            
            material.needsUpdate = true;
        }
        
        // 实时同步到场景中使用该材质的mesh
        this.syncMaterialToScene();
    }
    
    /**
     * ⭐ 将UI参数同步到selectedMaterialData（修复应用材质时参数不一致的问题）
     */
    syncUIToMaterialData() {
        if (!this.selectedMaterialData) return;
        
        // 同步颜色
        const colorInput = document.getElementById('mat-color');
        if (colorInput) {
            this.selectedMaterialData.color = colorInput.value;
        }
        
        // 同步金属度
        const metalnessInput = document.getElementById('mat-metalness');
        if (metalnessInput) {
            this.selectedMaterialData.metalness = parseFloat(metalnessInput.value);
        }
        
        // 同步粗糙度
        const roughnessInput = document.getElementById('mat-roughness');
        if (roughnessInput) {
            this.selectedMaterialData.roughness = parseFloat(roughnessInput.value);
        }
        
        // 同步不透明度
        const opacityInput = document.getElementById('mat-opacity');
        if (opacityInput) {
            this.selectedMaterialData.opacity = parseFloat(opacityInput.value);
        }
        
        // 同步自发光颜色
        const emissiveInput = document.getElementById('mat-emissive');
        if (emissiveInput) {
            this.selectedMaterialData.emissive = emissiveInput.value;
        }
        
        // 同步自发光强度
        const emissiveIntensityInput = document.getElementById('mat-emissive-intensity');
        if (emissiveIntensityInput) {
            this.selectedMaterialData.emissiveIntensity = parseFloat(emissiveIntensityInput.value);
        }
        
        // 同步双面显示
        const doubleSidedInput = document.getElementById('mat-double-sided');
        if (doubleSidedInput) {
            this.selectedMaterialData.doubleSided = doubleSidedInput.checked;
        }
        
        // 同步 Z-Fighting 设置
        const zfightingEnabled = document.getElementById('mat-zfighting-enabled');
        if (zfightingEnabled) {
            this.selectedMaterialData.polygonOffset = zfightingEnabled.checked;
            if (zfightingEnabled.checked) {
                const factorInput = document.getElementById('mat-zfighting-factor');
                const unitsInput = document.getElementById('mat-zfighting-units');
                this.selectedMaterialData.polygonOffsetFactor = factorInput ? parseFloat(factorInput.value) : 1;
                this.selectedMaterialData.polygonOffsetUnits = unitsInput ? parseFloat(unitsInput.value) : 1;
            } else {
                this.selectedMaterialData.polygonOffsetFactor = 0;
                this.selectedMaterialData.polygonOffsetUnits = 0;
            }
        }
        
        // 同步凹凸强度
        const bumpScaleInput = document.getElementById('mat-bump-scale');
        if (bumpScaleInput) {
            this.selectedMaterialData.bumpScale = parseFloat(bumpScaleInput.value);
        }
        
        // 同步AO强度
        const aoIntensityInput = document.getElementById('mat-ao-intensity');
        if (aoIntensityInput) {
            this.selectedMaterialData.aoIntensity = parseFloat(aoIntensityInput.value);
        }
        
        // 同步贴图强度参数
        const mapIntensityInput = document.getElementById('mat-map-intensity');
        if (mapIntensityInput) {
            this.selectedMaterialData.mapIntensity = parseFloat(mapIntensityInput.value);
        }
        
        const normalScaleInput = document.getElementById('mat-normal-scale');
        if (normalScaleInput) {
            const scaleValue = parseFloat(normalScaleInput.value);
            this.selectedMaterialData.normalScale = { x: scaleValue, y: scaleValue };
        }
        
        const roughnessMapIntensityInput = document.getElementById('mat-roughness-map-intensity');
        if (roughnessMapIntensityInput) {
            this.selectedMaterialData.roughnessMapIntensity = parseFloat(roughnessMapIntensityInput.value);
        }
        
        const metalnessMapIntensityInput = document.getElementById('mat-metalness-map-intensity');
        if (metalnessMapIntensityInput) {
            this.selectedMaterialData.metalnessMapIntensity = parseFloat(metalnessMapIntensityInput.value);
        }
        
        // 同步UV调整参数
        const uvRepeatX = document.getElementById('mat-uv-repeat-x');
        if (uvRepeatX) {
            this.selectedMaterialData.uvRepeatX = parseFloat(uvRepeatX.value);
        }
        
        const uvRepeatY = document.getElementById('mat-uv-repeat-y');
        if (uvRepeatY) {
            this.selectedMaterialData.uvRepeatY = parseFloat(uvRepeatY.value);
        }
        
        const uvOffsetX = document.getElementById('mat-uv-offset-x');
        if (uvOffsetX) {
            this.selectedMaterialData.uvOffsetX = parseFloat(uvOffsetX.value);
        }
        
        const uvOffsetY = document.getElementById('mat-uv-offset-y');
        if (uvOffsetY) {
            this.selectedMaterialData.uvOffsetY = parseFloat(uvOffsetY.value);
        }
        
        const uvRotation = document.getElementById('mat-uv-rotation');
        if (uvRotation) {
            this.selectedMaterialData.uvRotation = parseFloat(uvRotation.value);
        }
        
        const uvCenterX = document.getElementById('mat-uv-center-x');
        if (uvCenterX) {
            this.selectedMaterialData.uvCenterX = parseFloat(uvCenterX.value);
        }
        
        const uvCenterY = document.getElementById('mat-uv-center-y');
        if (uvCenterY) {
            this.selectedMaterialData.uvCenterY = parseFloat(uvCenterY.value);
        }
    }
    
    /**
     * 应用UV变换到材质的所有纹理
     * @param {THREE.Material} material - 材质对象
     */
    applyUVTransformToMaterial(material) {
        if (!material) return;
        
        // 读取UV参数
        const uvRepeatX = parseFloat(document.getElementById('mat-uv-repeat-x')?.value || 1);
        const uvRepeatY = parseFloat(document.getElementById('mat-uv-repeat-y')?.value || 1);
        const uvOffsetX = parseFloat(document.getElementById('mat-uv-offset-x')?.value || 0);
        const uvOffsetY = parseFloat(document.getElementById('mat-uv-offset-y')?.value || 0);
        const uvRotation = parseFloat(document.getElementById('mat-uv-rotation')?.value || 0);
        const uvCenterX = parseFloat(document.getElementById('mat-uv-center-x')?.value || 0.5);
        const uvCenterY = parseFloat(document.getElementById('mat-uv-center-y')?.value || 0.5);
        
        // 对所有贴图应用UV变换
        const textureProps = ['map', 'normalMap', 'bumpMap', 'aoMap', 'roughnessMap', 'metalnessMap', 'emissiveMap'];
        
        textureProps.forEach(prop => {
            const texture = material[prop];
            if (texture) {
                texture.repeat.set(uvRepeatX, uvRepeatY);
                texture.offset.set(uvOffsetX, uvOffsetY);
                texture.rotation = uvRotation;
                texture.center.set(uvCenterX, uvCenterY);
                texture.needsUpdate = true;
            }
        });
    }
    
    /**
     * 将当前材质参数同步到场景中使用该材质的所有mesh
     */
    syncMaterialToScene() {
        if (!this.selectedMaterial || !this.selectedMaterialData) return;
        
        const currentScene = window.manager?.getCurrentScene();
        if (!currentScene || !currentScene.scene) return;
        
        const materialId = this.selectedMaterial.displayName;
        
        // 遍历场景中的所有对象，找到使用该材质的mesh
        currentScene.scene.traverse((object) => {
            if (object.isMesh && object.material && object.material.userData.materialId === materialId) {
                // 更新mesh的材质参数
                this.updateMeshMaterial(object);
            }
        });
    }
    
    /**
     * 更新单个mesh的材质参数
     * @param {THREE.Mesh} mesh - 要更新的mesh
     */
    updateMeshMaterial(mesh) {
        if (!mesh || !mesh.material) return;
        
        const material = mesh.material;
        
        // 更新材质参数
        const colorInput = document.getElementById('mat-color');
        if (colorInput) {
            material.color.set(colorInput.value);
        }
        
        const metalnessInput = document.getElementById('mat-metalness');
        if (metalnessInput && material.metalness !== undefined) {
            material.metalness = parseFloat(metalnessInput.value);
        }
        
        const roughnessInput = document.getElementById('mat-roughness');
        if (roughnessInput && material.roughness !== undefined) {
            material.roughness = parseFloat(roughnessInput.value);
        }
        
        const opacityInput = document.getElementById('mat-opacity');
        if (opacityInput) {
            material.opacity = parseFloat(opacityInput.value);
            material.transparent = material.opacity < 1;
        }
        
        const emissiveInput = document.getElementById('mat-emissive');
        if (emissiveInput && material.emissive) {
            material.emissive.set(emissiveInput.value);
        }
        
        const emissiveIntensityInput = document.getElementById('mat-emissive-intensity');
        if (emissiveIntensityInput && material.emissiveIntensity !== undefined) {
            material.emissiveIntensity = parseFloat(emissiveIntensityInput.value);
        }
        
        const doubleSidedInput = document.getElementById('mat-double-sided');
        if (doubleSidedInput) {
            material.side = doubleSidedInput.checked ? THREE.DoubleSide : THREE.FrontSide;
        }
        
        // 🔧 修复：根据不同情况使用不同的透明策略
        if (material.map || material.alphaMap || material.opacity < 1) {
            // 透明材质（包括贴图和半透明）
            if (material.map || material.alphaMap) {
                // 有贴图：使用alphaTest进行像素级裁剪
                material.alphaTest = 0.5;
            } else {
                material.alphaTest = 0;
            }
            // 统一启用透明模式，避免双面自遮挡
            material.transparent = true;
            material.depthWrite = false;
            material.depthTest = true;
        }
        
        // 更新贴图强度参数
        const mapIntensityInput = document.getElementById('mat-map-intensity');
        if (mapIntensityInput) {
            material.userData.mapIntensity = parseFloat(mapIntensityInput.value);
        }
        
        const normalScaleInput = document.getElementById('mat-normal-scale');
        if (normalScaleInput && material.normalMap) {
            const normalScale = parseFloat(normalScaleInput.value);
            material.normalScale = new THREE.Vector2(normalScale, normalScale);
        }
        
        const roughnessMapIntensityInput = document.getElementById('mat-roughness-map-intensity');
        if (roughnessMapIntensityInput) {
            material.userData.roughnessMapIntensity = parseFloat(roughnessMapIntensityInput.value);
        }
        
        const metalnessMapIntensityInput = document.getElementById('mat-metalness-map-intensity');
        if (metalnessMapIntensityInput) {
            material.userData.metalnessMapIntensity = parseFloat(metalnessMapIntensityInput.value);
        }
        
        material.needsUpdate = true;
    }
    
    /**
     * 加载贴图并应用到场景中使用该材质的所有模型
     * @param {string} textureType - 贴图类型（map, normalMap, bumpMap等）
     * @param {Object} textureData - 贴图数据（包含id, url, path等）
     */
    async loadAndApplyTextureToScene(textureType, textureData) {
        if (!this.selectedMaterial || !this.selectedMaterialData) return;
        
        try {
            // 获取后端URL
            const backendUrl = window.globalConfig?.backendUrl || 'http://localhost:7284';
            
            // 检查textureData.url是否已经是完整URL
            let textureUrl;
            if (textureData.url && (textureData.url.startsWith('http://') || textureData.url.startsWith('https://'))) {
                // 已经是完整URL，直接使用
                textureUrl = textureData.url;
            } else {
                // 相对路径，需要添加backendUrl
                const relativePath = textureData.url || textureData.path;
                textureUrl = relativePath.startsWith('/') 
                    ? `${backendUrl}${relativePath}`
                    : `${backendUrl}/${relativePath}`;
            }
            
            console.log(`🖼️ 加载贴图: ${textureType} from ${textureUrl}`);
            
            // 使用Three.js加载贴图
            const textureLoader = new THREE.TextureLoader();
            const texture = await new Promise((resolve, reject) => {
                textureLoader.load(
                    textureUrl,
                    (tex) => {
                        resolve(tex);
                    },
                    undefined,
                    (error) => {
                        console.error(`❌ 贴图加载失败: ${textureType}`, error);
                        reject(error);
                    }
                );
            });
            
            // 设置贴图属性
            if (textureType === 'map') {
                texture.colorSpace = THREE.SRGBColorSpace;
            }
            
            // 设置贴图的wrapping模式（用于UV重复）
            texture.wrapS = THREE.RepeatWrapping;
            texture.wrapT = THREE.RepeatWrapping;
            
            // 应用UV变换
            this.applyUVTransformToTexture(texture);
            
            // ⭐ 将贴图添加到 ResourcePreloader 缓存中，避免后续重复加载
            // 使用多个 key（id、name、displayName）指向同一个纹理对象，提高缓存命中率
            if (window.resourcePreloader && textureData.id) {
                // 主 key：使用 ID
                const idKey = `/api/projects/${this.projectId}/textures/${textureData.id}/file`;
                window.resourcePreloader.textureCache.set(idKey, texture);
                
                // 额外 key：使用 name（如果与 id 不同）
                if (textureData.name && textureData.name !== textureData.id) {
                    const nameKey = `/api/projects/${this.projectId}/textures/${textureData.name}/file`;
                    window.resourcePreloader.textureCache.set(nameKey, texture);
                }
                
                // 额外 key：使用 displayName（如果与 id 和 name 都不同）
                if (textureData.displayName && 
                    textureData.displayName !== textureData.id && 
                    textureData.displayName !== textureData.name) {
                    const displayNameKey = `/api/projects/${this.projectId}/textures/${textureData.displayName}/file`;
                    window.resourcePreloader.textureCache.set(displayNameKey, texture);
                }
            }
            
            // 应用到场景中所有使用该材质的mesh
            const currentScene = window.manager?.getCurrentScene();
            if (currentScene && currentScene.scene) {
                const materialId = this.selectedMaterial.displayName;
                let appliedCount = 0;
                
                currentScene.scene.traverse((object) => {
                    if (object.isMesh && object.material && object.material.userData.materialId === materialId) {
                        // 应用贴图到材质
                        object.material[textureType] = texture;
                        object.material.needsUpdate = true;
                        appliedCount++;
                    }
                });
            }
            
            // 同时应用到预览球
            if (this.previewMesh && this.previewMesh.material) {
                this.previewMesh.material[textureType] = texture;
                this.previewMesh.material.needsUpdate = true;
            }
            
        } catch (error) {
            console.error(`❌ 加载并应用贴图失败: ${textureType}`, error);
            throw error;
        }
    }
    
    /**
     * 应用UV变换到单个贴图
     * @param {THREE.Texture} texture - 要应用变换的贴图
     */
    applyUVTransformToTexture(texture) {
        if (!texture) return;
        
        // 读取UV变换参数
        const uvRepeatX = parseFloat(document.getElementById('mat-uv-repeat-x')?.value || 1);
        const uvRepeatY = parseFloat(document.getElementById('mat-uv-repeat-y')?.value || 1);
        const uvOffsetX = parseFloat(document.getElementById('mat-uv-offset-x')?.value || 0);
        const uvOffsetY = parseFloat(document.getElementById('mat-uv-offset-y')?.value || 0);
        const uvRotation = parseFloat(document.getElementById('mat-uv-rotation')?.value || 0);
        const uvCenterX = parseFloat(document.getElementById('mat-uv-center-x')?.value || 0.5);
        const uvCenterY = parseFloat(document.getElementById('mat-uv-center-y')?.value || 0.5);
        
        // 应用变换
        texture.repeat.set(uvRepeatX, uvRepeatY);
        texture.offset.set(uvOffsetX, uvOffsetY);
        texture.rotation = uvRotation;
        texture.center.set(uvCenterX, uvCenterY);
        texture.needsUpdate = true;
    }
    
    /**
     * 从场景中的所有使用该材质的模型移除贴图
     * @param {string} textureType - 贴图类型（map, normalMap, bumpMap等）
     */
    removeTextureFromScene(textureType) {
        if (!this.selectedMaterial) return;
        
        try {
            // 从场景中所有使用该材质的mesh移除贴图
            const currentScene = window.manager?.getCurrentScene();
            if (currentScene && currentScene.scene) {
                const materialId = this.selectedMaterial.displayName;
                let removedCount = 0;
                
                currentScene.scene.traverse((object) => {
                    if (object.isMesh && object.material && object.material.userData.materialId === materialId) {
                        // 移除贴图
                        if (object.material[textureType]) {
                            object.material[textureType] = null;
                            object.material.needsUpdate = true;
                            removedCount++;
                        }
                    }
                });
            }
            
            // 同时从预览球移除
            if (this.previewMesh && this.previewMesh.material) {
                if (this.previewMesh.material[textureType]) {
                    this.previewMesh.material[textureType] = null;
                    this.previewMesh.material.needsUpdate = true;
                }
            }
            
        } catch (error) {
            console.error(`❌ 从场景移除贴图失败: ${textureType}`, error);
        }
    }
    
    /**
     * 同步range和number输入
     */
    syncRangeAndNumber(rangeId, numberId) {
        const range = document.getElementById(rangeId);
        const number = document.getElementById(numberId);
        
        if (range && number) {
            range.addEventListener('input', () => {
                number.value = range.value;
            });
            
            number.addEventListener('input', () => {
                range.value = number.value;
            });
        }
    }
    
    /**
     * 同步颜色选择器和HEX输入
     */
    syncColorAndHex(colorId, hexId) {
        const color = document.getElementById(colorId);
        const hex = document.getElementById(hexId);
        
        if (color && hex) {
            color.addEventListener('input', () => {
                hex.value = color.value;
            });
            
            hex.addEventListener('input', () => {
                if (/^#[0-9A-Fa-f]{6}$/.test(hex.value)) {
                    color.value = hex.value;
                }
            });
        }
    }
    
    /**
     * 同步UV旋转：滑块用弧度，数字输入用角度
     */
    syncUVRotation() {
        const range = document.getElementById('mat-uv-rotation');
        const number = document.getElementById('mat-uv-rotation-value');
        
        if (range && number) {
            // 滑块变化：弧度 -> 角度
            range.addEventListener('input', () => {
                const radians = parseFloat(range.value);
                const degrees = Math.round(radians * 180 / Math.PI);
                number.value = degrees;
                this.markAsUnsaved();
                this.updatePreview();
            });
            
            // 数字输入变化：角度 -> 弧度
            number.addEventListener('input', () => {
                const degrees = parseFloat(number.value);
                const radians = degrees * Math.PI / 180;
                range.value = radians.toFixed(2);
                this.markAsUnsaved();
                this.updatePreview();
            });
        }
    }
    
    /**
     * 创建新材质（打开模态框）
     */
    createNewMaterial() {
        const modal = document.getElementById('create-material-modal');
        if (!modal) return;
        
        // 清空表单
        document.getElementById('new-material-display-name').value = '';
        
        // 显示模态框
        modal.classList.add('active');
        
        // 聚焦到名称输入框
        setTimeout(() => {
            document.getElementById('new-material-display-name').focus();
        }, 100);
    }
    
    /**
     * 生成唯一的材质ID
     */
    generateMaterialId() {
        const timestamp = Date.now();
        const random = Math.random().toString(36).substring(2, 8);
        return `material_${timestamp}_${random}`;
    }
    
    /**
     * 关闭新建材质模态框
     */
    closeCreateMaterialModal() {
        const modal = document.getElementById('create-material-modal');
        if (modal) {
            modal.classList.remove('active');
        }
    }
    
    /**
     * 确认创建新材质
     */
    async confirmCreateMaterial() {
        const displayName = document.getElementById('new-material-display-name').value.trim();
        const materialType = 'MeshPhysicalMaterial'; // 固定使用物理材质
        
        // 验证显示名称
        if (!displayName) {
            if (window.showManageMessage) {
                window.showManageMessage('请输入材质名称', 'warning');
            } else {
                alert('请输入材质名称');
            }
            document.getElementById('new-material-display-name').focus();
            return;
        }
        
        // ⭐ 检查材质名称是否重复
        const isDuplicate = this.materials.some(m => 
            (m.displayName || m.name) === displayName
        );
        
        if (isDuplicate) {
            if (window.showManageMessage) {
                window.showManageMessage(`材质名称 "${displayName}" 已存在，请使用其他名称`, 'warning');
            } else {
                alert(`材质名称 "${displayName}" 已存在，请使用其他名称`);
            }
            document.getElementById('new-material-display-name').focus();
            return;
        }
        
        try {
            // 自动生成唯一ID
            const materialId = this.generateMaterialId();
            
            // 根据材质类型设置默认参数
            const defaultParams = {
                name: materialId,  // 使用自动生成的ID作为name
                displayName: displayName,
                type: materialType,
                description: '',
                color: '#ffffff',
                opacity: 1.0,
                doubleSided: false
            };
            
            // 根据材质类型添加特定参数
            if (materialType === 'MeshStandardMaterial' || materialType === 'MeshPhysicalMaterial') {
                defaultParams.metalness = 0.5;
                defaultParams.roughness = 0.5;
                defaultParams.emissive = '#000000';
                defaultParams.emissiveIntensity = 0;
                defaultParams.aoIntensity = 1.0;
                defaultParams.bumpScale = 0.0;
            } else if (materialType === 'MeshPhongMaterial') {
                defaultParams.shininess = 30;
                defaultParams.emissive = '#000000';
                defaultParams.specular = '#111111';
            } else if (materialType === 'MeshLambertMaterial') {
                defaultParams.emissive = '#000000';
            }
            // MeshBasicMaterial 只需要基础参数
            
            await this.materialLibraryManager.createMaterial(defaultParams);
            await this.loadMaterials();
            
            // 关闭模态框
            this.closeCreateMaterialModal();
            
            // 显示成功消息
            if (window.showManageMessage) {
                window.showManageMessage(`材质 "${displayName}" 创建成功！`, 'success');
            } else {
                alert('材质创建成功！');
            }
            
            // 自动选中新创建的材质
            const newMaterial = this.materials.find(m => m.displayName === displayName);
            if (newMaterial) {
                await this.selectMaterial(newMaterial.displayName);
                
                // ⭐ 自动应用到当前选中的mesh（如果有）
                const sceneTreeUI = window.sceneTreeUI;
                const hasMeshSelected = (sceneTreeUI?.selectedMeshes?.length > 0) || sceneTreeUI?._currentSelectedMesh;
                
                if (hasMeshSelected) {
                    // 延迟一下确保材质数据已加载
                    setTimeout(async () => {
                        try {
                            await this.applyMaterialToSelectedMesh();
                            console.log('✅ [Material Panel] 已自动应用新创建的材质');
                        } catch (error) {
                            console.error('❌ 自动应用材质失败:', error);
                        }
                    }, 100);
                }
            }
            
        } catch (error) {
            console.error('❌ 创建材质失败:', error);
            alert('创建材质失败: ' + error.message);
        }
    }
    
    /**
     * 保存材质
     */
    async saveMaterial() {
        if (!this.selectedMaterial) return;
        
        try {
            // 辅助函数：获取贴图ID（支持新旧两种格式）
            const getTextureId = (textureType) => {
                return this.selectedMaterialData?.textures?.[textureType]?.id 
                    || this.selectedMaterialData?.[textureType] 
                    || null;
            };
            
            const materialData = {
                type: this.selectedMaterial.type || 'MeshStandardMaterial', // 保留材质类型
                color: document.getElementById('mat-color').value,
                metalness: parseFloat(document.getElementById('mat-metalness').value),
                roughness: parseFloat(document.getElementById('mat-roughness').value),
                opacity: parseFloat(document.getElementById('mat-opacity').value),
                emissive: document.getElementById('mat-emissive').value,
                emissiveIntensity: parseFloat(document.getElementById('mat-emissive-intensity').value),
                bumpScale: parseFloat(document.getElementById('mat-bump-scale').value),
                aoIntensity: parseFloat(document.getElementById('mat-ao-intensity').value),
                doubleSided: document.getElementById('mat-double-sided').checked,
                map: getTextureId('map'),
                normalMap: getTextureId('normalMap'),
                bumpMap: getTextureId('bumpMap'),
                aoMap: getTextureId('aoMap'),
                roughnessMap: getTextureId('roughnessMap'),
                metalnessMap: getTextureId('metalnessMap'),
                // 贴图强度参数
                mapIntensity: parseFloat(document.getElementById('mat-map-intensity').value),
                normalScale: { x: parseFloat(document.getElementById('mat-normal-scale').value), y: parseFloat(document.getElementById('mat-normal-scale').value) },
                roughnessMapIntensity: parseFloat(document.getElementById('mat-roughness-map-intensity').value),
                metalnessMapIntensity: parseFloat(document.getElementById('mat-metalness-map-intensity').value),
                // UV调整参数
                uvRepeatX: parseFloat(document.getElementById('mat-uv-repeat-x').value),
                uvRepeatY: parseFloat(document.getElementById('mat-uv-repeat-y').value),
                uvOffsetX: parseFloat(document.getElementById('mat-uv-offset-x').value),
                uvOffsetY: parseFloat(document.getElementById('mat-uv-offset-y').value),
                uvRotation: parseFloat(document.getElementById('mat-uv-rotation').value),
                uvCenterX: parseFloat(document.getElementById('mat-uv-center-x').value),
                uvCenterY: parseFloat(document.getElementById('mat-uv-center-y').value),
                // Z-Fighting 修复参数
                polygonOffset: document.getElementById('mat-zfighting-enabled')?.checked || false,
                polygonOffsetFactor: document.getElementById('mat-zfighting-enabled')?.checked ? parseFloat(document.getElementById('mat-zfighting-factor')?.value || 1) : 0,
                polygonOffsetUnits: document.getElementById('mat-zfighting-enabled')?.checked ? parseFloat(document.getElementById('mat-zfighting-units')?.value || 1) : 0
            };
            
            console.log('💾 [保存材质] 准备保存材质数据:', {
                materialId: this.selectedMaterial.displayName,
                materialName: this.selectedMaterial.displayName,
                map: materialData.map,
                normalMap: materialData.normalMap,
                bumpMap: materialData.bumpMap,
                aoMap: materialData.aoMap,
                roughnessMap: materialData.roughnessMap,
                metalnessMap: materialData.metalnessMap
            });
            
            await this.materialLibraryManager.updateMaterial(this.selectedMaterial.displayName, materialData);
            console.log('✅ [保存材质] 材质保存成功');
            
            await this.loadMaterials();
            
            // 🔄 更新场景中所有使用该材质的mesh
            await this.updateSceneMaterials(this.selectedMaterial.displayName, materialData);
            
            // 标记为已保存
            this.markAsSaved();
            
            if (window.showManageMessage) {
                window.showManageMessage('材质保存成功！', 'success');
            }
        } catch (error) {
            console.error('❌ 保存材质失败:', error);
            if (window.showManageMessage) {
                window.showManageMessage('保存材质失败: ' + error.message, 'error');
            }
        }
    }
    
    /**
     * 更新场景中所有使用指定材质的mesh
     * @param {string} materialDisplayName - 材质显示名称
     * @param {Object} materialData - 材质数据
     */
    async updateSceneMaterials(materialDisplayName, materialData) {
        try {
            console.log(`🔄 [更新场景材质] 开始更新场景中使用材质 "${materialDisplayName}" 的所有mesh`);
            
            // 获取场景树管理器
            const sceneTreeManager = window.manager?.sceneTreeManager;
            if (!sceneTreeManager) {
                console.warn('⚠️ [更新场景材质] 场景树管理器不存在');
                return;
            }
            
            // 获取所有节点
            const allNodes = Array.from(sceneTreeManager.nodesMap.values());
            let updatedCount = 0;
            
            // 遍历所有节点，找到使用该材质的mesh
            for (const node of allNodes) {
                if (!node.object3D) continue;
                
                // 获取节点的模型组件
                const modelComponent = node.components?.find(c => c.type === 'model');
                if (!modelComponent || !modelComponent.meshMaterials) continue;
                
                // 检查该节点是否有使用该材质的mesh
                const meshesUsingMaterial = Object.entries(modelComponent.meshMaterials)
                    .filter(([meshName, matName]) => matName === materialDisplayName);
                
                if (meshesUsingMaterial.length === 0) continue;
                
                // 遍历使用该材质的mesh并更新
                for (const [meshName, matName] of meshesUsingMaterial) {
                    const meshObject = node.object3D.getObjectByName(meshName);
                    
                    if (!meshObject || !meshObject.isMesh) {
                        console.warn(`   ⚠️ 未找到Mesh: ${meshName}`);
                        continue;
                    }
                    
                    // 释放旧材质
                    if (meshObject.material) {
                        if (meshObject.material.map) meshObject.material.map.dispose();
                        if (meshObject.material.normalMap) meshObject.material.normalMap.dispose();
                        if (meshObject.material.bumpMap) meshObject.material.bumpMap.dispose();
                        if (meshObject.material.aoMap) meshObject.material.aoMap.dispose();
                        if (meshObject.material.roughnessMap) meshObject.material.roughnessMap.dispose();
                        if (meshObject.material.metalnessMap) meshObject.material.metalnessMap.dispose();
                        meshObject.material.dispose();
                    }
                    
                    // 创建新材质并应用
                    const newMaterial = await this.createThreeMaterialFromDataAsync(materialData);
                    newMaterial.userData.materialId = materialDisplayName;
                    newMaterial.userData.materialName = materialDisplayName;
                    
                    meshObject.material = newMaterial;
                    meshObject.material.needsUpdate = true;
                    
                    updatedCount++;
                    console.log(`   ✅ 更新Mesh: ${meshName} (节点: ${node.name})`);
                }
            }
            
            console.log(`✅ [更新场景材质] 完成，共更新 ${updatedCount} 个mesh`);
            
            // 触发场景渲染
            if (window.manager && window.manager.render) {
                window.manager.render();
            }
            
        } catch (error) {
            console.error('❌ [更新场景材质] 更新失败:', error);
        }
    }
    
    /**
     * 异步版本的创建材质方法（支持贴图加载完成后返回）
     * @param {Object} materialData - 材质数据
     * @returns {Promise<THREE.Material>} Three.js材质对象
     */
    async createThreeMaterialFromDataAsync(materialData) {
        const MaterialClass = THREE[materialData.type] || THREE.MeshStandardMaterial;
        
        const params = {
            name: materialData.name || 'Material',
            color: new THREE.Color(materialData.color || '#ffffff'),
            opacity: materialData.opacity !== undefined ? materialData.opacity : 1.0,
            // 🔧 修复：透明相关参数 - 避免transparent和alphaTest冲突
            transparent: materialData.transparent !== undefined ? materialData.transparent : false,
            alphaTest: materialData.alphaTest !== undefined ? materialData.alphaTest : 0,
            depthWrite: materialData.depthWrite !== undefined ? materialData.depthWrite : true,
            depthTest: true,
            side: materialData.doubleSided ? THREE.DoubleSide : THREE.FrontSide
        };
        
        // 根据材质类型添加特定参数
        if (materialData.type === 'MeshStandardMaterial' || materialData.type === 'MeshPhysicalMaterial') {
            params.metalness = materialData.metalness !== undefined ? materialData.metalness : 0.5;
            params.roughness = materialData.roughness !== undefined ? materialData.roughness : 0.5;
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
            params.emissiveIntensity = materialData.emissiveIntensity !== undefined ? materialData.emissiveIntensity : 0;
        } else if (materialData.type === 'MeshPhongMaterial') {
            params.shininess = materialData.shininess !== undefined ? materialData.shininess : 30;
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
            params.specular = new THREE.Color(materialData.specular || '#111111');
        } else if (materialData.type === 'MeshLambertMaterial') {
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
        }
        
        const material = new MaterialClass(params);
        
        // 应用额外的材质属性（如AO强度、凹凸强度等）
        if (materialData.aoIntensity !== undefined && material.aoMapIntensity !== undefined) {
            material.aoMapIntensity = materialData.aoIntensity;
        }
        if (materialData.bumpScale !== undefined && material.bumpScale !== undefined) {
            material.bumpScale = materialData.bumpScale;
        }
        
        // 应用贴图强度参数到userData
        if (materialData.mapIntensity !== undefined) {
            material.userData.mapIntensity = materialData.mapIntensity;
        }
        if (materialData.roughnessMapIntensity !== undefined) {
            material.userData.roughnessMapIntensity = materialData.roughnessMapIntensity;
        }
        if (materialData.metalnessMapIntensity !== undefined) {
            material.userData.metalnessMapIntensity = materialData.metalnessMapIntensity;
        }
        
        // 应用UV变换参数
        const uvTransform = {
            repeat: new THREE.Vector2(
                materialData.uvRepeatX !== undefined ? materialData.uvRepeatX : 1,
                materialData.uvRepeatY !== undefined ? materialData.uvRepeatY : 1
            ),
            offset: new THREE.Vector2(
                materialData.uvOffsetX !== undefined ? materialData.uvOffsetX : 0,
                materialData.uvOffsetY !== undefined ? materialData.uvOffsetY : 0
            ),
            rotation: materialData.uvRotation !== undefined ? materialData.uvRotation : 0,
            center: new THREE.Vector2(
                materialData.uvCenterX !== undefined ? materialData.uvCenterX : 0.5,
                materialData.uvCenterY !== undefined ? materialData.uvCenterY : 0.5
            )
        };
        
        // 加载纹理贴图（异步）
        const textureLoader = new THREE.TextureLoader();
        const backendUrl = window.APP_CONFIG?.backendUrl || window.location.origin;
        
        // 辅助函数：通过纹理ID获取完整路径
        const getTexturePath = (textureId) => {
            if (!textureId) return null;
            if (textureId.startsWith('/')) return textureId; // 已经是路径
            return `/api/projects/${this.projectId}/textures/${textureId}/file`;
        };
        
        const texturePromises = [];
        
        // 基础颜色贴图
        if (materialData.map) {
            const texturePath = getTexturePath(materialData.map);
            if (texturePath) {
                texturePromises.push(
                    new Promise((resolve, reject) => {
                        textureLoader.load(
                            `${backendUrl}${texturePath}`,
                        (texture) => {
                            texture.colorSpace = THREE.SRGBColorSpace;
                            texture.repeat.copy(uvTransform.repeat);
                            texture.offset.copy(uvTransform.offset);
                            texture.rotation = uvTransform.rotation;
                            texture.center.copy(uvTransform.center);
                            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                            material.map = texture;
                            
                            // 🔧 修复：透明贴图智能检测（与SceneTreeManager保持一致）
                            const mapPath = String(texturePath).toLowerCase();
                            // 检查是否为透明格式：文件名后缀 或 纹理本身包含Alpha通道
                            const isTransparentFormat = mapPath.match(/\.(png|tga|webp)$/i) || texture.format === THREE.RGBAFormat;
                            
                            // 检查是否为马路线材质
                            const matName = (materialData.displayName || materialData.name || '').toLowerCase();
                            const isRoadLine = mapPath.includes('road') || mapPath.includes('line') || mapPath.includes('马路') || mapPath.includes('线') ||
                                             matName.includes('road') || matName.includes('line') || matName.includes('马路') || matName.includes('线');

                            if (isTransparentFormat || isRoadLine) {
                                if (isRoadLine) {
                                    // 🛣️ 马路线专用策略
                                    material.alphaTest = 0.1;
                                    material.transparent = false;
                                    material.depthWrite = true;
                                    material.side = THREE.DoubleSide;
                                    console.log(`   🛣️ [编辑器] 检测到马路线贴图，自动启用alphaTest模式`);
                                } else if (!material.transparent && material.alphaTest === 0) {
                                    // 🌿 普通透明物体：仅当用户未显式设置透明时，才自动启用
                                    material.alphaTest = 0.5;
                                    material.transparent = true;
                                    material.depthWrite = false;
                                    console.log(`   ✓ [编辑器] 检测到透明贴图，自动启用transparent模式`);
                                }
                                material.userData.needsRenderOrder = true;
                            }

                            material.needsUpdate = true;
                            resolve();
                        },
                        undefined,
                        (error) => {
                            console.warn('加载基础颜色贴图失败:', error);
                            resolve(); // 即使失败也继续
                        }
                    );
                    })
                );
            }
        }
        
        // 法线贴图
        if (materialData.normalMap) {
            const texturePath = getTexturePath(materialData.normalMap);
            if (texturePath) {
                texturePromises.push(
                    new Promise((resolve, reject) => {
                        textureLoader.load(
                            `${backendUrl}${texturePath}`,
                            (texture) => {
                                texture.repeat.copy(uvTransform.repeat);
                                texture.offset.copy(uvTransform.offset);
                                texture.rotation = uvTransform.rotation;
                                texture.center.copy(uvTransform.center);
                                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                                material.normalMap = texture;
                                if (materialData.normalScale !== undefined) {
                                    const normalScale = typeof materialData.normalScale === 'object' 
                                        ? (materialData.normalScale.x || 1) 
                                        : materialData.normalScale;
                                    material.normalScale = new THREE.Vector2(normalScale, normalScale);
                                }
                                material.needsUpdate = true;
                                resolve();
                            },
                            undefined,
                            (error) => {
                                console.warn('加载法线贴图失败:', error);
                                resolve();
                            }
                        );
                    })
                );
            }
        }
        
        // 凹凸贴图
        if (materialData.bumpMap) {
            const texturePath = getTexturePath(materialData.bumpMap);
            if (texturePath) {
                texturePromises.push(
                    new Promise((resolve, reject) => {
                        textureLoader.load(
                            `${backendUrl}${texturePath}`,
                        (texture) => {
                            texture.repeat.copy(uvTransform.repeat);
                            texture.offset.copy(uvTransform.offset);
                            texture.rotation = uvTransform.rotation;
                            texture.center.copy(uvTransform.center);
                            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                            material.bumpMap = texture;
                            material.needsUpdate = true;
                            resolve();
                        },
                        undefined,
                        (error) => {
                            console.warn('加载凹凸贴图失败:', error);
                            resolve();
                        }
                    );
                    })
                );
            }
        }
        
        // AO贴图
        if (materialData.aoMap) {
            const texturePath = getTexturePath(materialData.aoMap);
            if (texturePath) {
                texturePromises.push(
                    new Promise((resolve, reject) => {
                        textureLoader.load(
                            `${backendUrl}${texturePath}`,
                        (texture) => {
                            texture.repeat.copy(uvTransform.repeat);
                            texture.offset.copy(uvTransform.offset);
                            texture.rotation = uvTransform.rotation;
                            texture.center.copy(uvTransform.center);
                            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                            material.aoMap = texture;
                            material.needsUpdate = true;
                            resolve();
                        },
                        undefined,
                        (error) => {
                            console.warn('加载AO贴图失败:', error);
                            resolve();
                        }
                    );
                    })
                );
            }
        }
        
        // 粗糙度贴图
        if (materialData.roughnessMap) {
            const texturePath = getTexturePath(materialData.roughnessMap);
            if (texturePath) {
                texturePromises.push(
                    new Promise((resolve, reject) => {
                        textureLoader.load(
                            `${backendUrl}${texturePath}`,
                        (texture) => {
                            texture.repeat.copy(uvTransform.repeat);
                            texture.offset.copy(uvTransform.offset);
                            texture.rotation = uvTransform.rotation;
                            texture.center.copy(uvTransform.center);
                            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                            material.roughnessMap = texture;
                            material.needsUpdate = true;
                            resolve();
                        },
                        undefined,
                        (error) => {
                            console.warn('加载粗糙度贴图失败:', error);
                            resolve();
                        }
                    );
                    })
                );
            }
        }
        
        // 金属度贴图
        if (materialData.metalnessMap) {
            const texturePath = getTexturePath(materialData.metalnessMap);
            if (texturePath) {
                texturePromises.push(
                    new Promise((resolve, reject) => {
                        textureLoader.load(
                            `${backendUrl}${texturePath}`,
                        (texture) => {
                            texture.repeat.copy(uvTransform.repeat);
                            texture.offset.copy(uvTransform.offset);
                            texture.rotation = uvTransform.rotation;
                            texture.center.copy(uvTransform.center);
                            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                            material.metalnessMap = texture;
                            material.needsUpdate = true;
                            resolve();
                        },
                        undefined,
                        (error) => {
                            console.warn('加载金属度贴图失败:', error);
                            resolve();
                        }
                    );
                    })
                );
            }
        }
        
        // 等待所有贴图加载完成
        await Promise.all(texturePromises);
        
        return material;
    }
    
    /**
     * 显示未保存更改确认对话框
     * @returns {Promise<string>} 返回用户选择: 'save' | 'discard' | 'cancel'
     */
    showUnsavedChangesDialog() {
        return new Promise((resolve) => {
            const currentMaterialName = this.selectedMaterial?.displayName || this.selectedMaterial?.name || '当前材质';
            
            const modalHtml = `
                <div class="material-modal active" id="unsaved-changes-modal">
                    <div class="material-modal-content">
                        <div class="material-modal-header">
                            <h3>⚠️ 未保存的修改</h3>
                            <button class="material-modal-close" onclick="window.materialEditorPanel.resolveUnsavedDialog('cancel')">×</button>
                        </div>
                        <div class="material-modal-body">
                            <p>材质 <strong>"${currentMaterialName}"</strong> 有未保存的修改</p>
                            <p class="warning-text">是否保存修改？</p>
                        </div>
                        <div class="material-modal-footer">
                            <button class="material-btn-secondary" onclick="window.materialEditorPanel.resolveUnsavedDialog('discard')">不保存</button>
                            <button class="material-btn-secondary" onclick="window.materialEditorPanel.resolveUnsavedDialog('cancel')">取消</button>
                            <button class="material-btn-primary" onclick="window.materialEditorPanel.resolveUnsavedDialog('save')">保存</button>
                        </div>
                    </div>
                </div>
            `;
            
            document.body.insertAdjacentHTML('beforeend', modalHtml);
            
            // 存储resolve函数供按钮调用
            this._unsavedDialogResolve = resolve;
        });
    }
    
    /**
     * 检查未保存状态（用于关闭面板时）
     * @returns {Promise<boolean>} 返回是否可以继续关闭/操作
     */
    async checkUnsavedBeforeClose() {
        if (!this.hasUnsavedChanges) {
            return true; // 没有未保存的修改，可以关闭
        }
        
        const userChoice = await this.showUnsavedChangesDialog();
        
        if (userChoice === 'save') {
            await this.saveMaterial();
            return !this.hasUnsavedChanges; // 保存成功才能关闭
        } else if (userChoice === 'cancel') {
            return false; // 用户取消，不关闭
        } else {
            // 'discard' - 不保存，允许关闭
            return true;
        }
    }
    
    /**
     * 解析未保存更改对话框的用户选择
     * @param {string} choice - 用户选择: 'save' | 'discard' | 'cancel'
     */
    resolveUnsavedDialog(choice) {
        const modal = document.getElementById('unsaved-changes-modal');
        if (modal) modal.remove();
        
        if (this._unsavedDialogResolve) {
            this._unsavedDialogResolve(choice);
            this._unsavedDialogResolve = null;
        }
    }
    
    /**
     * 保存列表项名称（功能已移除）
     */
    async saveListItemName(item, materialId) {
        // 如果不在编辑状态，直接返回
        if (item.dataset.editing !== 'true') return;
        
        const nameDisplay = item.querySelector('.material-item-name-display');
        const nameInput = item.querySelector('.material-item-name-input');
        
        if (!nameDisplay || !nameInput) return;
        
        const newDisplayName = nameInput.value.trim();
        const material = this.materials.find(m => m.displayName === materialId);
        
        if (!material) return;
        
        // 验证名称
        if (!newDisplayName) {
            if (window.showManageMessage) {
                window.showManageMessage('材质名称不能为空', 'warning');
            }
            // 恢复原值
            nameInput.value = material.displayName || material.name;
            return;
        }
        
        // 如果名称未改变，直接退出
        if (newDisplayName === (material.displayName || material.name)) {
            this.exitListItemEditMode(item);
            return;
        }
        
        // ⭐ 检查材质名称是否与其他材质重复
        const isDuplicate = this.materials.some(m => 
            m.displayName !== materialId && (m.displayName || m.name) === newDisplayName
        );
        
        if (isDuplicate) {
            if (window.showManageMessage) {
                window.showManageMessage(`材质名称 "${newDisplayName}" 已存在，请使用其他名称`, 'warning');
            }
            // 恢复原值
            nameInput.value = material.displayName || material.name;
            nameInput.focus();
            nameInput.select();
            return;
        }
        
        // ⚠️ 重要提示：重命名材质会影响后续模型上传时的材质匹配
        const oldName = material.displayName || material.name;
        const confirmed = confirm(
            `⚠️ 重要提示\n\n` +
            `您正在将材质 "${oldName}" 重命名为 "${newDisplayName}"。\n\n` +
            `请注意：\n` +
            `• 材质名称用于匹配上传模型中的材质\n` +
            `• 重命名后，后续上传的模型如果材质名称与 "${newDisplayName}" 不匹配，将无法自动复用此材质设置\n` +
            `• 如果您的模型文件中材质名称是 "${oldName}"，建议保持名称不变\n\n` +
            `是否确认重命名？`
        );
        
        if (!confirmed) {
            // 用户取消重命名，恢复原值
            nameInput.value = oldName;
            this.exitListItemEditMode(item);
            return;
        }
        
        try {
            await this.materialLibraryManager.updateMaterial(materialId, {
                displayName: newDisplayName
            });
            
            // 更新显示
            nameDisplay.textContent = newDisplayName;
            material.displayName = newDisplayName;
            
            // 如果是当前选中的材质，也更新内存中的数据
            if (this.selectedMaterial?.id === materialId) {
                this.selectedMaterial.displayName = newDisplayName;
                if (this.selectedMaterialData) {
                    this.selectedMaterialData.displayName = newDisplayName;
                }
            }
            
            this.exitListItemEditMode(item);
            
            if (window.showManageMessage) {
                window.showManageMessage('材质重命名成功', 'success');
            }
        } catch (error) {
            console.error('❌ 重命名失败:', error);
            if (window.showManageMessage) {
                window.showManageMessage('重命名失败: ' + error.message, 'error');
            }
            // 恢复原值
            nameInput.value = material.displayName || material.name;
            this.exitListItemEditMode(item);
        }
    }
    
    /**
     * 取消列表项编辑
     */
    cancelListItemEdit(item, materialId) {
        const nameInput = item.querySelector('.material-item-name-input');
        const material = this.materials.find(m => m.displayName === materialId);
        
        // 恢复原值
        if (nameInput && material) {
            nameInput.value = material.displayName || material.name;
        }
        
        this.exitListItemEditMode(item);
    }
    
    /**
     * 退出列表项编辑模式
     */
    exitListItemEditMode(item) {
        const nameDisplay = item.querySelector('.material-item-name-display');
        const nameInput = item.querySelector('.material-item-name-input');
        
        if (!nameDisplay || !nameInput) return;
        
        // 显示文本，隐藏输入框
        nameDisplay.style.display = 'block';
        nameInput.style.display = 'none';
        
        // 清除编辑状态
        delete item.dataset.editing;
    }
    
    /**
     * 复制材质（打开模态框）
     */
    async duplicateMaterial() {
        if (!this.selectedMaterial || !this.selectedMaterialData) return;
        
        // 检查是否有未保存的修改
        if (this.hasUnsavedChanges) {
            const userChoice = await this.showUnsavedChangesDialog();
            
            if (userChoice === 'save') {
                await this.saveMaterial();
                if (this.hasUnsavedChanges) return; // 保存失败，不复制
            } else if (userChoice === 'cancel') {
                return; // 用户取消复制
            }
            // 'discard' 继续复制
        }
        
        const modal = document.getElementById('duplicate-material-modal');
        if (!modal) return;
        
        // 设置默认名称为原材质名称 + (副本)
        const defaultName = (this.selectedMaterialData.displayName || this.selectedMaterial.name) + ' (副本)';
        document.getElementById('duplicate-material-display-name').value = defaultName;
        
        // 显示模态框
        modal.classList.add('active');
        
        // 聚焦到名称输入框并选中文本
        setTimeout(() => {
            const input = document.getElementById('duplicate-material-display-name');
            input.focus();
            input.select();
        }, 100);
    }
    
    /**
     * 关闭复制材质模态框
     */
    closeDuplicateMaterialModal() {
        const modal = document.getElementById('duplicate-material-modal');
        if (modal) {
            modal.classList.remove('active');
        }
    }
    
    /**
     * 确认复制材质
     */
    async confirmDuplicateMaterial() {
        if (!this.selectedMaterial || !this.selectedMaterialData) return;
        
        const newDisplayName = document.getElementById('duplicate-material-display-name').value.trim();
        
        // 验证名称
        if (!newDisplayName) {
            if (window.showManageMessage) {
                window.showManageMessage('请输入材质名称', 'warning');
            } else {
                alert('请输入材质名称');
            }
            document.getElementById('duplicate-material-display-name').focus();
            return;
        }
        
        // ⭐ 检查材质名称是否重复
        const isDuplicate = this.materials.some(m => 
            (m.displayName || m.name) === newDisplayName
        );
        
        if (isDuplicate) {
            if (window.showManageMessage) {
                window.showManageMessage(`材质名称 "${newDisplayName}" 已存在，请使用其他名称`, 'warning');
            } else {
                alert(`材质名称 "${newDisplayName}" 已存在，请使用其他名称`);
            }
            document.getElementById('duplicate-material-display-name').focus();
            return;
        }
        
        try {
            // 自动生成新的ID
            const newMaterialId = this.generateMaterialId();
            
            // 复制材质数据
            const newMaterialData = {
                ...this.selectedMaterialData,
                name: newMaterialId,  // 使用新生成的ID
                displayName: newDisplayName
            };
            
            // 删除不需要复制的字段
            delete newMaterialData.id;
            delete newMaterialData.createdAt;
            delete newMaterialData.updatedAt;
            
            await this.materialLibraryManager.createMaterial(newMaterialData);
            await this.loadMaterials();
            
            // 关闭模态框
            this.closeDuplicateMaterialModal();
            
            // 显示成功消息
            if (window.showManageMessage) {
                window.showManageMessage(`材质 "${newDisplayName}" 复制成功！`, 'success');
            } else {
                alert('材质复制成功！');
            }
            
            // 自动选中新创建的材质
            const newMaterial = this.materials.find(m => m.displayName === newDisplayName);
            if (newMaterial) {
                await this.selectMaterial(newMaterial.displayName);
            }
            
        } catch (error) {
            console.error('❌ 复制材质失败:', error);
            alert('复制材质失败: ' + error.message);
        }
    }
    
    /**
     * 重置相机
     */
    resetCamera() {
        if (this.previewCamera) {
            this.previewCamera.position.set(0, 0, 5);
            this.previewCamera.lookAt(0, 0, 0);
        }
    }
    
    /**
     * 清除纹理
     */
    async clearTexture(textureType) {
        // 获取当前贴图ID（支持新旧两种格式）
        const textureId = this.selectedMaterialData?.textures?.[textureType]?.id 
                       || this.selectedMaterialData?.[textureType];
        
        // 如果有贴图，先减少引用计数（使用材质的displayName）
        if (textureId) {
            const materialDisplayName = this.selectedMaterialData.displayName || this.selectedMaterialData.name;
            await this.removeTextureReference(textureId, materialDisplayName);
        }
        
        // 从材质数据中删除贴图引用（新格式）
        if (this.selectedMaterialData?.textures?.[textureType]) {
            delete this.selectedMaterialData.textures[textureType];
        }
        
        // 从材质数据中删除贴图引用（旧格式）
        if (this.selectedMaterialData?.[textureType]) {
            this.selectedMaterialData[textureType] = null;
        }
        
        // 清空输入框
        const input = document.getElementById(`mat-${textureType.replace(/([A-Z])/g, '-$1').toLowerCase()}`);
        if (input) {
            input.value = '';
        }
        
        // ⭐ 立即从场景中的模型移除贴图
        this.removeTextureFromScene(textureType);
        
        // 更新预览
        this.updatePreview();
        
        // 标记为未保存
        this.markAsUnsaved();
    }
    
    /**
     * ⚠️ 已弃用：不再使用此方法
     * 
     * 问题：此方法会在用户只选中节点时，自动返回节点的第一个mesh，
     * 导致用户误以为已经选中了mesh，但实际上没有。
     * 
     * 正确做法：使用 sceneTreeUI._currentSelectedMesh（Mesh结构面板中的选中mesh）
     * 或 sceneTreeUI.selectedMeshes（搜索窗口中的多选mesh）
     * 
     * @deprecated 此方法会在用户只选中节点时误判为已选中mesh
     * @returns {THREE.Mesh|null} Mesh对象
     */
    getCurrentSelectedMesh() {
        console.warn('⚠️ [Material Panel] getCurrentSelectedMesh() 已弃用');
        console.warn('   问题：会在只选中节点时自动返回第一个mesh，造成误判');
        console.warn('   请使用: sceneTreeUI._currentSelectedMesh 或 sceneTreeUI.selectedMeshes');
        
        // 尝试从TransformControls获取当前附加的对象
        const currentScene = window.manager?.getCurrentScene();
        if (currentScene && currentScene.transformControlsManager) {
            const transformControls = currentScene.transformControlsManager.transformControls;
            if (transformControls && transformControls.object) {
                const attachedObject = transformControls.object;
                if (attachedObject.isMesh) {
                    return attachedObject;
                }
            }
        }
        
        // 备选：从选中的节点获取
        const sceneTreeUI = window.sceneTreeUI;
        const selectedNode = sceneTreeUI?.treeManager?.selectedNode;
        if (selectedNode && selectedNode.object3D) {
            // 如果节点的根对象就是mesh
            if (selectedNode.object3D.isMesh) {
                return selectedNode.object3D;
            }
            
            // 如果节点包含mesh，返回第一个
            let firstMesh = null;
            selectedNode.object3D.traverse((obj) => {
                if (!firstMesh && obj.isMesh) {
                    firstMesh = obj;
                }
            });
            
            if (firstMesh) {
                return firstMesh;
            }
        }
        
        return null;
    }
    
    /**
     * 通过mesh对象找到它所属的节点（必须是有model组件的节点）
     * ⭐ 优先使用缓存，避免重复遍历
     * @param {THREE.Mesh} meshObject - Mesh对象
     * @returns {TreeNode|null} 节点对象
     */
    findNodeByMesh(meshObject) {
        const sceneTreeUI = window.sceneTreeUI;
        const sceneTreeManager = window.sceneTreeManager;
        
        if (!sceneTreeManager) {
            console.error('❌ sceneTreeManager不存在');
            return null;
        }
        
        // ⭐ 优先从缓存中查找（性能优化：O(1) vs O(N)）
        if (sceneTreeUI && sceneTreeUI.meshNodeCache) {
            const cachedNode = sceneTreeUI.meshNodeCache.get(meshObject.uuid);
            if (cachedNode) {
                return cachedNode;
            }
        }
        // 如果缓存未命中，遍历场景树中的所有节点，找到所有包含这个mesh的节点
        const matchingNodes = [];
        sceneTreeManager.traverse((node) => {
            if (!node.object3D) return; // 没有3D对象，跳过
            
            // ⭐ 只检查有model组件的节点（根节点没有model组件，会被跳过）
            const hasModelComponent = node.components && node.components.some(c => c.type === 'model');
            if (!hasModelComponent) return;
            
            // 遍历节点的3D对象树，查找mesh
            node.object3D.traverse((obj) => {
                if (obj === meshObject) {
                    matchingNodes.push(node);
                }
            });
        });
        
        if (matchingNodes.length === 0) {
            console.warn('   ⚠️ 未找到包含此Mesh的节点（有model组件的节点）');
            return null;
        }
        
        // 如果有多个匹配，选择最深层的节点（子节点优先于父节点）
        // 通过比较节点的层级深度来确定
        let foundNode = matchingNodes[0];
        let maxDepth = this.getNodeDepth(foundNode);
        
        for (let i = 1; i < matchingNodes.length; i++) {
            const depth = this.getNodeDepth(matchingNodes[i]);
            if (depth > maxDepth) {
                maxDepth = depth;
                foundNode = matchingNodes[i];
            }
        }
        if (matchingNodes.length > 1) {
        }
        
        // ⭐ 将查找结果加入缓存，下次可以直接使用
        if (sceneTreeUI && sceneTreeUI.meshNodeCache) {
            sceneTreeUI.meshNodeCache.set(meshObject.uuid, foundNode);
        }
        
        return foundNode;
    }
    
    /**
     * 获取节点的层级深度
     * @param {TreeNode} node - 节点对象
     * @returns {number} 深度（根节点为0）
     */
    getNodeDepth(node) {
        let depth = 0;
        let current = node.parent;
        while (current) {
            depth++;
            current = current.parent;
        }
        return depth;
    }
    
    /**
     * 应用材质到当前选中的mesh
     */
    async applyMaterialToSelectedMesh() {
        if (!this.selectedMaterial || !this.selectedMaterialData) {
            alert('请先选择一个材质');
            return;
        }
        
        // ⭐ 应用前先同步UI参数到materialData（确保使用最新值）
        this.syncUIToMaterialData();
        
        // 获取当前选中的mesh（从sceneTreeUI）
        const sceneTreeUI = window.sceneTreeUI;
        if (!sceneTreeUI) {
            alert('无法访问场景树UI');
            return;
        }
        
        // ⭐⭐⭐ 严格检查：必须在Mesh结构面板中明确选中mesh才能应用材质
        let selectedMeshItems = []; // 存储 {mesh, node} 对象
        
        // 1. 优先使用搜索多选模式的selectedMeshes（在搜索窗口中多选）
        if (sceneTreeUI.selectedMeshes && sceneTreeUI.selectedMeshes.length > 0) {
            // 多选模式：selectedMeshes已经存储了 {mesh, node, path} 对象
            selectedMeshItems = sceneTreeUI.selectedMeshes.map(item => ({
                mesh: item.mesh,
                node: item.node
            }));
        } 
        // 2. 检查Mesh结构面板中的单选mesh
        else if (sceneTreeUI._currentSelectedMesh) {
            // ⚠️ 只有在Mesh结构面板中明确选中了mesh，_currentSelectedMesh才会被设置
            const currentMesh = sceneTreeUI._currentSelectedMesh;
            // 查找mesh所属的节点
            const node = this.findNodeByMesh(currentMesh);
            selectedMeshItems = [{
                mesh: currentMesh,
                node: node
            }];
        }
        // 3. ❌ 如果没有明确选中mesh，拒绝应用
        else {
            if (window.showMessage) {
                window.showMessage('请先在Mesh结构面板中选择要应用材质的Mesh', 'warning', 4000);
            }
            console.warn('⚠️ [Material Panel] 未选中任何mesh，拒绝应用材质');
            return;
        }
        
        if (selectedMeshItems.length === 0) {
            if (window.showMessage) {
                window.showMessage('请先在Mesh结构面板中选中一个Mesh', 'warning', 3000);
            }
            return;
        }
        
        try {
            const materialId = this.selectedMaterial.displayName;
            const materialData = this.selectedMaterialData;
            // 应用到每个选中的mesh
            let savedCount = 0;
            for (const item of selectedMeshItems) {
                const meshObject = item.mesh;
                const node = item.node; // ⭐ 直接使用已有的node信息
                
                if (!meshObject || !meshObject.isMesh) {
                    console.warn('   ⚠️ 跳过非Mesh对象:', meshObject?.name);
                    continue;
                }
                if (!node) {
                    console.warn('   ⚠️ 无法找到Mesh所属的节点，跳过保存');
                }
                
                // 保存旧材质
                const oldMaterial = meshObject.material;
                
                // ⭐⭐ 移除旧材质的引用记录（如果存在）
                if (oldMaterial && !Array.isArray(oldMaterial)) {
                    const oldMaterialId = oldMaterial.userData?.materialId;
                    if (oldMaterialId) {
                        const sceneId = window.manager?.getCurrentSceneName() || 'unknown';
                        this.removeMaterialUsage(
                            oldMaterialId,
                            sceneId,
                            node?.id,
                            meshObject.uuid
                        );
                        console.log(`   🔄 [Material Panel] 移除旧材质引用: ${oldMaterialId} (mesh: ${meshObject.name})`);
                    }
                } else if (Array.isArray(oldMaterial)) {
                    // 多材质情况：移除每个材质的引用
                    const sceneId = window.manager?.getCurrentSceneName() || 'unknown';
                    oldMaterial.forEach(mat => {
                        const oldMaterialId = mat?.userData?.materialId;
                        if (oldMaterialId) {
                            this.removeMaterialUsage(
                                oldMaterialId,
                                sceneId,
                                node?.id,
                                meshObject.uuid
                            );
                            console.log(`   🔄 [Material Panel] 移除旧材质引用: ${oldMaterialId} (mesh: ${meshObject.name})`);
                        }
                    });
                }
                
                // 创建新的Three.js材质对象
                const newMaterial = this.createThreeMaterialFromData(materialData);
                // 保存材质ID到userData
                newMaterial.userData.materialId = materialId;
                newMaterial.userData.materialName = materialData.name;
                
                // ⭐ 释放旧材质（避免内存泄漏）
                if (oldMaterial) {
                    if (Array.isArray(oldMaterial)) {
                        // 多材质情况
                        oldMaterial.forEach(mat => {
                            if (mat && mat.dispose) {
                                mat.dispose();
                            }
                        });
                    } else if (oldMaterial.dispose) {
                        oldMaterial.dispose();
                    }
                }
                
                // 应用材质
                meshObject.material = newMaterial;
                meshObject.material.needsUpdate = true;
                
                // ⭐ 标记mesh需要更新
                if (meshObject.geometry) {
                    meshObject.geometry.attributes.position.needsUpdate = true;
                    if (meshObject.geometry.attributes.normal) {
                        meshObject.geometry.attributes.normal.needsUpdate = true;
                    }
                    if (meshObject.geometry.attributes.uv) {
                        meshObject.geometry.attributes.uv.needsUpdate = true;
                    }
                }
                
                // ⭐ 强制更新mesh的世界矩阵
                meshObject.updateMatrixWorld(true);
                // ⭐ 保存材质绑定到节点的model组件
                if (node && sceneTreeUI.saveMeshMaterialBinding) {
                    try {
                        await sceneTreeUI.saveMeshMaterialBinding(node, meshObject, materialId);
                        savedCount++;
                        
                        // ⭐ 记录材质使用
                        const sceneId = window.manager?.getCurrentSceneName() || 'unknown';
                        this.recordMaterialUsage(
                            materialId,
                            sceneId,
                            node.id,
                            node.name,
                            meshObject.uuid,
                            meshObject.name
                        );
                    } catch (error) {
                        console.error('   ❌ 保存材质绑定失败:', error);
                        console.error('      错误详情:', error.stack);
                    }
                }
            }
            // 显示成功消息
            if (savedCount === selectedMeshItems.length) {
                const message = `材质 "${materialData.displayName || materialData.name}" 已应用到 ${selectedMeshItems.length} 个Mesh并全部保存`;
                if (window.showManageMessage) {
                    window.showManageMessage(message, 'success');
                } else {
                    alert(message);
                }
            } else if (savedCount > 0) {
                const message = `材质已应用到 ${selectedMeshItems.length} 个Mesh，但只保存了 ${savedCount} 个绑定（部分mesh找不到所属节点）`;
                if (window.showManageMessage) {
                    window.showManageMessage(message, 'warning');
                } else {
                    alert(message);
                }
            } else {
                const message = `材质已应用到场景，但未保存任何绑定数据（刷新后会丢失）`;
                if (window.showManageMessage) {
                    window.showManageMessage(message, 'error');
                } else {
                    alert(message);
                }
            }
            // ⭐ 强制刷新渲染（多次调用确保更新）
            if (window.manager) {
                // 立即渲染一次
                if (window.manager.render) {
                    window.manager.render();
                }
                
                // 再次渲染确保材质更新生效（某些材质需要多帧才能正确显示）
                setTimeout(() => {
                    if (window.manager && window.manager.render) {
                        window.manager.render();
                    }
                }, 50);
                
                setTimeout(() => {
                    if (window.manager && window.manager.render) {
                        window.manager.render();
                    }
                }, 150);
            }
            
            // ⭐ 触发场景保存，持久化材质绑定数据（只在有保存成功时触发）
            if (savedCount > 0 && window.sceneTreeUI && window.sceneTreeUI.notifyTreeChanged) {
                window.sceneTreeUI.notifyTreeChanged();
            } else if (savedCount === 0) {
                console.warn('   ⚠️ 没有保存任何绑定，不触发场景保存');
            }
            
            // ⭐ 重新加载材质数据并刷新显示（确保使用计数同步）
            if (savedCount > 0) {
                // 给后端API一点时间完成写入
                await new Promise(resolve => setTimeout(resolve, 200));
                
                // 重新加载材质数据
                await this.refreshMaterialUsageAfterNodeChange();
            }
            
        } catch (error) {
            console.error('❌ 应用材质失败:', error);
            if (window.showManageMessage) {
                window.showManageMessage('应用材质失败: ' + error.message, 'error');
            }
        }
    }
    
    /**
     * 从材质数据创建Three.js材质对象
     * @param {Object} materialData - 材质数据
     * @returns {THREE.Material} Three.js材质对象
     */
    createThreeMaterialFromData(materialData) {
        const MaterialClass = THREE[materialData.type] || THREE.MeshStandardMaterial;
        
        const params = {
            name: materialData.name || 'Material',
            color: new THREE.Color(materialData.color || '#ffffff'),
            opacity: materialData.opacity !== undefined ? materialData.opacity : 1.0,
            // 🔧 修复：透明相关参数 - 避免transparent和alphaTest冲突
            transparent: materialData.transparent !== undefined ? materialData.transparent : false,
            alphaTest: materialData.alphaTest !== undefined ? materialData.alphaTest : 0,
            depthWrite: materialData.depthWrite !== undefined ? materialData.depthWrite : true,
            depthTest: true,
            side: materialData.doubleSided ? THREE.DoubleSide : THREE.FrontSide
        };
        
        // 根据材质类型添加特定参数
        if (materialData.type === 'MeshStandardMaterial' || materialData.type === 'MeshPhysicalMaterial') {
            params.metalness = materialData.metalness !== undefined ? materialData.metalness : 0.5;
            params.roughness = materialData.roughness !== undefined ? materialData.roughness : 0.5;
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
            params.emissiveIntensity = materialData.emissiveIntensity !== undefined ? materialData.emissiveIntensity : 0;
        } else if (materialData.type === 'MeshPhongMaterial') {
            params.shininess = materialData.shininess !== undefined ? materialData.shininess : 30;
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
            params.specular = new THREE.Color(materialData.specular || '#111111');
        } else if (materialData.type === 'MeshLambertMaterial') {
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
        }
        
        const material = new MaterialClass(params);
        
        // ⭐ 应用额外的材质属性（如AO强度、凹凸强度等）
        if (materialData.aoIntensity !== undefined && material.aoMapIntensity !== undefined) {
            material.aoMapIntensity = materialData.aoIntensity;
        }
        if (materialData.bumpScale !== undefined && material.bumpScale !== undefined) {
            material.bumpScale = materialData.bumpScale;
        }
        
        // ⭐ 应用贴图强度参数到userData
        if (materialData.mapIntensity !== undefined) {
            material.userData.mapIntensity = materialData.mapIntensity;
        }
        if (materialData.roughnessMapIntensity !== undefined) {
            material.userData.roughnessMapIntensity = materialData.roughnessMapIntensity;
        }
        if (materialData.metalnessMapIntensity !== undefined) {
            material.userData.metalnessMapIntensity = materialData.metalnessMapIntensity;
        }
        
        // ⭐ 加载纹理贴图
        const textureLoader = new THREE.TextureLoader();
        const backendUrl = window.APP_CONFIG?.backendUrl || window.location.origin;
        
        // 辅助函数：通过纹理ID获取完整路径
        const getTexturePath = async (textureId) => {
            if (!textureId) return null;
            if (textureId.startsWith('/')) return textureId; // 已经是路径
            return `/api/projects/${this.projectId}/textures/${textureId}/file`;
        };
        
        // 基础颜色贴图
        if (materialData.map) {
            const loadMap = async () => {
                const texturePath = await getTexturePath(materialData.map);
                if (!texturePath) return;
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        texture.colorSpace = THREE.SRGBColorSpace;
                        material.map = texture;
                        material.needsUpdate = true;
                        // 触发渲染更新
                        if (window.manager && window.manager.render) {
                            window.manager.render();
                        }
                    },
                    undefined,
                    (error) => console.warn('加载基础颜色贴图失败:', error)
                );
            };
            loadMap();
        }
        
        // 法线贴图
        if (materialData.normalMap) {
            const loadNormalMap = async () => {
                const texturePath = await getTexturePath(materialData.normalMap);
                if (!texturePath) return;
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        material.normalMap = texture;
                        // 应用法线贴图强度
                        if (materialData.normalScale !== undefined) {
                            const normalScale = typeof materialData.normalScale === 'object' 
                                ? (materialData.normalScale.x || 1) 
                                : materialData.normalScale;
                            material.normalScale = new THREE.Vector2(normalScale, normalScale);
                        }
                        material.needsUpdate = true;
                        // 触发渲染更新
                        if (window.manager && window.manager.render) {
                            window.manager.render();
                        }
                    },
                    undefined,
                    (error) => console.warn('加载法线贴图失败:', error)
                );
            };
            loadNormalMap();
        }
        
        // 凹凸贴图
        if (materialData.bumpMap) {
            const loadBumpMap = async () => {
                const texturePath = await getTexturePath(materialData.bumpMap);
                if (!texturePath) return;
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        material.bumpMap = texture;
                        material.needsUpdate = true;
                        // 触发渲染更新
                        if (window.manager && window.manager.render) {
                            window.manager.render();
                        }
                    },
                    undefined,
                    (error) => console.warn('加载凹凸贴图失败:', error)
                );
            };
            loadBumpMap();
        }
        
        // AO贴图
        if (materialData.aoMap) {
            const loadAOMap = async () => {
                const texturePath = await getTexturePath(materialData.aoMap);
                if (!texturePath) return;
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        material.aoMap = texture;
                        material.needsUpdate = true;
                        // 触发渲染更新
                        if (window.manager && window.manager.render) {
                            window.manager.render();
                        }
                    },
                    undefined,
                    (error) => console.warn('加载AO贴图失败:', error)
                );
            };
            loadAOMap();
        }
        
        // 金属度贴图
        if (materialData.metalnessMap && material.metalnessMap !== undefined) {
            const loadMetalnessMap = async () => {
                const texturePath = await getTexturePath(materialData.metalnessMap);
                if (!texturePath) return;
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        material.metalnessMap = texture;
                        material.needsUpdate = true;
                        // 触发渲染更新
                        if (window.manager && window.manager.render) {
                            window.manager.render();
                        }
                    },
                    undefined,
                    (error) => console.warn('加载金属度贴图失败:', error)
                );
            };
            loadMetalnessMap();
        }
        
        // 粗糙度贴图
        if (materialData.roughnessMap && material.roughnessMap !== undefined) {
            textureLoader.load(
                `${backendUrl}${materialData.roughnessMap}`,
                (texture) => {
                    material.roughnessMap = texture;
                    material.needsUpdate = true;
                    // 触发渲染更新
                    if (window.manager && window.manager.render) {
                        window.manager.render();
                    }
                },
                undefined,
                (error) => console.warn('加载粗糙度贴图失败:', error)
            );
        }
        
        // 自发光贴图
        if (materialData.emissiveMap && material.emissiveMap !== undefined) {
            const loadEmissiveMap = async () => {
                const texturePath = await getTexturePath(materialData.emissiveMap);
                if (!texturePath) return;
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        texture.colorSpace = THREE.SRGBColorSpace;
                        material.emissiveMap = texture;
                        material.needsUpdate = true;
                        // 触发渲染更新
                        if (window.manager && window.manager.render) {
                            window.manager.render();
                        }
                    },
                    undefined,
                    (error) => console.warn('加载自发光贴图失败:', error)
                );
            };
            loadEmissiveMap();
        }
        return material;
    }
    
    /**
     * ==========================================
     * 材质使用追踪系统
     * ==========================================
     */
    
    /**
     * 显示当前材质的使用情况
     */
    async showMaterialUsage() {
        if (!this.selectedMaterial) {
            alert('请先选择一个材质');
            return;
        }
        
        // 刷新材质数据
        await this.refreshMaterialUsageAfterNodeChange();
        
        // 从后端API获取最新数据
        const projectId = this.projectId || window.projectManager?.getCurrentProject()?.id;
        let backendData = null;
        try {
            const response = await fetch(`/api/projects/${projectId}/materials/${encodeURIComponent(this.selectedMaterial.displayName)}?_t=${Date.now()}`);
            const result = await response.json();
            if (result.success) {
                backendData = result.data;
            }
        } catch (error) {
            console.error('❌ 获取材质数据失败:', error);
        }
        
        // 检查前后端数据一致性
        const latestMaterialData = this.materials.find(m => 
            m.displayName === this.selectedMaterial.displayName
        );
        
        if (latestMaterialData && backendData) {
            if (backendData.usedByMeshes?.length !== latestMaterialData.usedByMeshes?.length) {
                console.warn(`⚠️ 数据不一致: 后端${backendData.usedByMeshes?.length}个 vs 前端${latestMaterialData.usedByMeshes?.length}个`);
                this.selectedMaterialData = backendData;
            }
        }
        
        const usage = this.getMaterialUsage(this.selectedMaterial.displayName);
        const materialName = this.selectedMaterialData.displayName || this.selectedMaterialData.name;
        
        if (usage.count === 0) {
            const message = `材质 "${materialName}" 当前未被任何Mesh使用`;
            if (window.showManageMessage) {
                window.showManageMessage(message, 'info');
            } else {
                alert(message);
            }
            return;
        }
        
        // ⭐ 获取当前场景信息（用于显示场景名称和筛选按钮）
        const currentSceneId = window.manager?.getCurrentSceneName();
        
        // ⭐ 对场景进行排序，将当前场景排到第一个
        const sortedScenes = [...usage.scenes].sort((a, b) => {
            const aIsCurrent = a.sceneId === currentSceneId;
            const bIsCurrent = b.sceneId === currentSceneId;
            if (aIsCurrent && !bIsCurrent) return -1; // a是当前场景，排前面
            if (!aIsCurrent && bIsCurrent) return 1;  // b是当前场景，排前面
            return 0; // 其他场景保持原顺序
        });
        
        // 构建详细的使用信息HTML
        let detailsHTML = `
            <div class="material-usage-panel">
                <div class="usage-panel-header">
                    <h3>📋 Mesh引用信息</h3>
                    <button class="usage-panel-close" onclick="window.materialEditorPanel.closeMaterialUsagePanel()">✕</button>
                </div>
                <div class="usage-panel-content">
                    <div class="usage-summary">
                        <div class="usage-material-name">${materialName}</div>
                        <div class="usage-stats">共在 <strong>${usage.count}</strong> 个Mesh上使用</div>
                    </div>
                    <div class="usage-details">
        `;
        
        // 遍历每个场景（优先显示当前场景）
        sortedScenes.forEach(scene => {
            const sceneName = this.getSceneName(scene.sceneId);
            const isCurrentScene = scene.sceneId === currentSceneId;
            
            detailsHTML += `
                <div class="usage-scene">
                    <div class="usage-scene-header">
                        <div class="usage-scene-info">
                            <span class="usage-scene-label">场景</span>
                            <span class="usage-scene-name">${sceneName}</span>
                            ${isCurrentScene ? '<span class="current-scene-badge">当前</span>' : ''}
                        </div>
                        ${isCurrentScene ? `
                            <button class="btn-show-in-search" 
                                    onclick="window.materialEditorPanel.showMaterialMeshesInSearch('${this.selectedMaterial.displayName}', '${scene.sceneId}')">
                                📋 显示到搜索窗口
                            </button>
                        ` : ''}
                    </div>
            `;
            
            // 遍历每个节点
            scene.nodes.forEach(node => {
                detailsHTML += `
                    <div class="usage-node">
                        <div class="usage-node-header">
                            <span class="usage-node-icon">📦</span>
                            <span class="usage-node-name">${node.nodeName}</span>
                            <span class="usage-node-count">${node.meshCount} 个Mesh</span>
                        </div>
                        <div class="usage-meshes">
                `;
                
                // 遍历每个mesh
                node.meshes.forEach(mesh => {
                    // mesh 对象结构: { meshId, meshName }
                    const meshDisplayName = mesh.meshName || mesh.meshId || 'Unknown';
                    const meshIdShort = mesh.meshId ? mesh.meshId.substring(0, 12) : '';
                    
                    detailsHTML += `
                        <div class="usage-mesh-item">
                            <span class="usage-mesh-icon">🔷</span>
                            <span class="usage-mesh-name">${meshDisplayName}</span>
                            ${meshIdShort ? `<span class="usage-mesh-uuid">${meshIdShort}</span>` : ''}
                        </div>
                    `;
                });
                
                detailsHTML += `
                        </div>
                    </div>
                `;
            });
            
            detailsHTML += `
                </div>
            `;
        });
        
        detailsHTML += `
                        </div>
                    </div>
                </div>
            </div>
        `;
        
        // 显示在材质编辑器面板的panel-content内
        const editorPanel = document.getElementById('material-editor-panel');
        if (!editorPanel) {
            console.error('❌ 材质编辑器面板不存在');
            return;
        }
        
        const panelContent = editorPanel.querySelector('.panel-content');
        if (!panelContent) {
            console.error('❌ panel-content不存在');
            return;
        }
        
        // 创建覆盖层容器
        let overlay = panelContent.querySelector('.material-usage-overlay-container');
        if (!overlay) {
            overlay = document.createElement('div');
            overlay.className = 'material-usage-overlay-container';
            panelContent.appendChild(overlay);
        }
        
        overlay.innerHTML = detailsHTML;
        overlay.style.display = 'block';
    }
    
    /**
     * 获取场景名称
     * @param {string} sceneId - 场景ID
     * @returns {string} 场景名称
     */
    getSceneName(sceneId) {
        try {
            // 检查projectManager是否存在
            if (!window.projectManager) {
                console.warn(`⚠️ window.projectManager 不存在`);
                return sceneId;
            }
            
            // 方法1: 从projectManager.getSceneById获取
            if (window.projectManager.getSceneById) {
                const scene = window.projectManager.getSceneById(sceneId);
                if (scene && scene.name) {
                    return scene.name;
                }
            }
            
            // 方法2: 从场景列表获取
            if (window.projectManager.getScenes) {
                const scenes = window.projectManager.getScenes();
                if (scenes && Array.isArray(scenes)) {
                    const scene = scenes.find(s => s.id === sceneId);
                    if (scene && scene.name) {
                        return scene.name;
                    }
                }
            }
            
            // 方法3: 从currentProject获取
            if (window.projectManager.currentProject) {
                if (window.projectManager.currentProject.scenes) {
                    const scene = window.projectManager.currentProject.scenes.find(s => s.id === sceneId);
                    if (scene && scene.name) {
                        return scene.name;
                    }
                }
            }
            
            console.warn(`⚠️ 所有方法都未找到场景名称，sceneId=${sceneId}`);
        } catch (error) {
            console.error('❌ 获取场景名称失败:', error);
        }
        
        return sceneId; // 返回sceneId作为后备
    }
    
    /**
     * 将材质引用的mesh显示到搜索窗口
     * @param {string} materialId - 材质ID
     * @param {string} sceneId - 场景ID
     */
    async showMaterialMeshesInSearch(materialId, sceneId) {
        // 关闭使用情况面板
        this.closeMaterialUsagePanel();
        
        // ⭐ 优先从材质JSON的usedByMeshes加载引用数据
        const materialData = this.materials.find(m => m.displayName === materialId);
        if (materialData && materialData.usedByMeshes && materialData.usedByMeshes.length > 0) {
            // 使用后端数据构建scene usage
            const meshesInScene = materialData.usedByMeshes.filter(ref => ref.sceneId === sceneId);
            
            if (meshesInScene.length === 0) {
                if (window.showManageMessage) {
                    window.showManageMessage('该材质在当前场景中未被使用', 'info');
                }
                return;
            }
            
            // 按节点分组
            const nodeMap = new Map();
            for (const ref of meshesInScene) {
                if (!nodeMap.has(ref.nodeId)) {
                    nodeMap.set(ref.nodeId, {
                        nodeId: ref.nodeId,
                        nodeName: ref.nodeId, // 暂时用nodeId，实际在查找时会更新
                        meshes: []
                    });
                }
                nodeMap.get(ref.nodeId).meshes.push({
                    uuid: ref.meshId,
                    name: ref.meshName || ref.meshId
                });
            }
            
            const sceneUsage = {
                sceneId: sceneId,
                nodes: Array.from(nodeMap.values())
            };
            
            await this.selectMeshesByUsageData(sceneUsage);
            return;
        }
        
        // 降级：使用前端内存中的数据
        const usage = this.getMaterialUsage(materialId);
        const sceneUsage = usage.scenes.find(s => s.sceneId === sceneId);
        
        if (!sceneUsage) {
            console.warn('⚠️ 未找到场景的使用信息');
            if (window.showManageMessage) {
                window.showManageMessage('该材质在当前场景中未被使用', 'info');
            }
            return;
        }
        
        // 使用SceneTreeUI的搜索功能
        const sceneTreeUI = window.sceneTreeUI;
        if (!sceneTreeUI) {
            console.error('❌ sceneTreeUI不存在');
            return;
        }
        
        // ⭐ 直接使用引用信息中的数据构建搜索结果
        await this.selectMeshesByUsageData(sceneUsage);
    }
    
    /**
     * 根据材质使用数据选中mesh
     * @param {Object} sceneUsage - 场景使用信息 {sceneId, nodes: [{nodeId, nodeName, meshes: [{uuid, name}]}]}
     */
    async selectMeshesByUsageData(sceneUsage) {
        const sceneTreeUI = window.sceneTreeUI;
        if (!sceneTreeUI) {
            console.error('❌ sceneTreeUI不存在');
            return;
        }
        
        // 清空当前搜索
        if (sceneTreeUI.clearMeshSearch) {
            sceneTreeUI.clearMeshSearch();
        }
        
        // 收集匹配的mesh对象
        const matchedMeshes = [];
        const sceneTreeManager = window.sceneTreeManager;
        
        if (!sceneTreeManager) {
            console.error('❌ sceneTreeManager不存在');
            return;
        }
        // 遍历每个节点的引用信息
        sceneUsage.nodes.forEach(nodeUsage => {
            const nodeId = nodeUsage.nodeId;
            const nodeName = nodeUsage.nodeName;
            
            // 在场景树中查找对应的节点
            let treeNode = null;
            sceneTreeManager.traverse((node) => {
                if (node.id === nodeId) {
                    treeNode = node;
                }
            });
            
            if (!treeNode) {
                console.warn(`⚠️ 未找到节点: ${nodeName} (ID: ${nodeId})`);
                return;
            }
            
            // 在节点的object3D中查找mesh
            if (treeNode.object3D) {
                // 收集该节点下需要查找的mesh名称
                // ⭐ 使用name而不是uuid，因为meshMaterials的key是mesh的name
                const targetNames = new Set(nodeUsage.meshes.map(m => m.name || m.uuid));
                
                treeNode.object3D.traverse((obj) => {
                    if (obj.isMesh && obj.name && targetNames.has(obj.name)) {
                        matchedMeshes.push({
                            mesh: obj,
                            node: treeNode,
                            nodeName: treeNode.name,
                            path: [obj.name || '(unnamed)']
                        });
                    }
                });
            }
        });
        if (matchedMeshes.length === 0) {
            if (window.showManageMessage) {
                window.showManageMessage('未找到使用该材质的mesh', 'warning');
            } else {
                alert('未找到使用该材质的mesh');
            }
            return;
        }
        
        // 设置为搜索模式
        sceneTreeUI.meshSearchMatches = matchedMeshes;
        sceneTreeUI.meshSearchKeyword = `材质引用 (${matchedMeshes.length}个)`;
        sceneTreeUI.selectedMeshes = [...matchedMeshes];
        
        // ⭐ 使用统一的显示mesh面板方法（内部处理补位逻辑）
        const meshPanel = sceneTreeUI.showMeshPanel();
        
        if (meshPanel) {
            const treeContainer = meshPanel.querySelector('.mesh-tree-container');
            if (treeContainer) {
                // 渲染搜索结果
                treeContainer.innerHTML = sceneTreeUI.renderMeshSearchResults();
                
                // 绑定事件
                sceneTreeUI.bindMeshSearchSelectionEvents(meshPanel);
            }
            
            // 更新搜索框的值
            const searchInput = document.getElementById('mesh-search-input');
            if (searchInput) {
                searchInput.value = sceneTreeUI.meshSearchKeyword;
            }
        } else {
            console.warn('⚠️ mesh-structure-panel面板不存在');
        }
        
        // 选中第一个mesh
        if (matchedMeshes.length > 0) {
            sceneTreeUI.selectMeshInSearchMode(matchedMeshes[0]);
        }
        
        // 显示成功消息
        const message = `已在搜索窗口中显示 ${matchedMeshes.length} 个使用该材质的Mesh`;
        if (window.showManageMessage) {
            window.showManageMessage(message, 'success');
        } else {
            alert(message);
        }
    }
    
    /**
     * 关闭材质使用情况面板
     */
    closeMaterialUsagePanel() {
        const editorPanel = document.getElementById('material-editor-panel');
        if (editorPanel) {
            const panelContent = editorPanel.querySelector('.panel-content');
            if (panelContent) {
                const overlay = panelContent.querySelector('.material-usage-overlay-container');
                if (overlay) {
                    overlay.style.display = 'none';
                }
            }
        }
    }
    
    /**
     * 关闭所有弹窗（预览窗口、引用信息面板等）
     */
    closeAllPopups() {
        // 关闭预览窗口
        this.hidePreviewWindow();
        
        // 关闭Mesh引用信息面板
        this.closeMaterialUsagePanel();
    }
    
    /**
     * ⭐ 构建材质使用映射
     * ✅ 新版本：直接从材质JSON的usedByMeshes字段读取，无需扫描场景
     */
    async buildMaterialUsageMap() {
        // ✅ 新架构下不需要扫描场景，材质引用已经保存在材质JSON中
        // 保留此方法是为了向后兼容，但实际上getMaterialUsage会直接读取usedByMeshes
        console.log('✅ [Material Usage] 使用材质JSON的usedByMeshes字段，无需构建映射');
    }
    
    /**
     * ⭐ 从后台API获取场景的nodes数据
     * @param {string} sceneId - 场景ID
     * @returns {Promise<Object>} nodes数据
     */
    async fetchSceneNodes(sceneId) {
        try {
            const projectId = this.projectId || window.projectManager?.getCurrentProject()?.id;
            if (!projectId) {
                throw new Error('项目ID不存在');
            }
            
            const response = await fetch(`/api/projects/${projectId}/scenes/${sceneId}/nodes`);
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}`);
            }
            
            const result = await response.json();
            if (result.success) {
                return result.data;
            } else {
                throw new Error(result.error || '获取失败');
            }
        } catch (error) {
            console.error(`获取场景 ${sceneId} 的nodes失败:`, error);
            return null;
        }
    }
    
    /**
     * ⭐ 从数据记录材质使用（用于从后台数据构建映射）
     */
    recordMaterialUsageFromData(materialId, sceneId, nodeId, nodeName, meshUuid, meshName) {
        // 确保材质ID存在
        if (!this.materialUsageMap.has(materialId)) {
            this.materialUsageMap.set(materialId, new Map());
        }
        
        const materialScenes = this.materialUsageMap.get(materialId);
        
        // 确保场景ID存在
        if (!materialScenes.has(sceneId)) {
            materialScenes.set(sceneId, new Map());
        }
        
        const sceneNodes = materialScenes.get(sceneId);
        
        // 确保节点ID存在
        if (!sceneNodes.has(nodeId)) {
            sceneNodes.set(nodeId, {
                nodeName,
                meshes: new Map()
            });
        }
        
        const nodeData = sceneNodes.get(nodeId);
        
        // ⭐⭐ 修复：确保meshes是Map类型（兼容旧数据结构）
        if (!(nodeData.meshes instanceof Map)) {
            // 如果是数组或其他类型，转换为Map
            const oldMeshes = nodeData.meshes;
            nodeData.meshes = new Map();
            
            // 如果原来是数组，迁移数据
            if (Array.isArray(oldMeshes)) {
                oldMeshes.forEach(mesh => {
                    nodeData.meshes.set(mesh.uuid || mesh.meshId, {
                        uuid: mesh.uuid || mesh.meshId,
                        name: mesh.name || mesh.meshName
                    });
                });
            }
        }
        
        // 添加mesh（使用Map避免重复）
        if (!nodeData.meshes.has(meshUuid)) {
            nodeData.meshes.set(meshUuid, {
                uuid: meshUuid,
                name: meshName
            });
        }
    }
    
    /**
     * 获取材质的使用信息
     * @param {string} materialId - 材质ID
     * @returns {Object} { count, scenes: [...] }
     */
    getMaterialUsage(materialId) {
        // ✅ 从材质JSON的usedByMeshes字段读取引用数据
        const materialData = this.materials.find(m => m.displayName === materialId || m.name === materialId);
        
        if (!materialData || !materialData.usedByMeshes || !Array.isArray(materialData.usedByMeshes)) {
            return { count: 0, scenes: [] };
        }
        
        // 按场景分组统计
        const sceneMap = new Map();
        
        for (const ref of materialData.usedByMeshes) {
            const { sceneId, nodeId, meshId, meshName } = ref;
            
            if (!sceneMap.has(sceneId)) {
                sceneMap.set(sceneId, new Map());
            }
            
            const nodeMap = sceneMap.get(sceneId);
            if (!nodeMap.has(nodeId)) {
                nodeMap.set(nodeId, {
                    nodeId,
                    nodeName: this.getNodeName(sceneId, nodeId), // 尝试获取节点名称
                    meshes: []
                });
            }
            
            nodeMap.get(nodeId).meshes.push({
                meshId,
                meshName: meshName || meshId
            });
        }
        
        // 转换为返回格式
        const scenes = [];
        let totalCount = 0;
        
        for (const [sceneId, nodeMap] of sceneMap.entries()) {
            const nodes = Array.from(nodeMap.values()).map(nodeData => ({
                nodeId: nodeData.nodeId,
                nodeName: nodeData.nodeName,
                meshCount: nodeData.meshes.length,
                meshes: nodeData.meshes
            }));
            
            const meshCount = nodes.reduce((sum, node) => sum + node.meshCount, 0);
            totalCount += meshCount;
            
            scenes.push({
                sceneId,
                nodeCount: nodes.length,
                nodes
            });
        }
        
        return {
            count: totalCount,
            scenes
        };
    }
    
    /**
     * 获取节点名称（辅助方法）
     */
    getNodeName(sceneId, nodeId) {
        // 如果是当前场景，尝试从场景树获取
        const currentSceneId = window.manager?.getCurrentSceneName();
        if (sceneId === currentSceneId && window.manager?.sceneTreeManager) {
            const node = window.manager.sceneTreeManager.nodesMap.get(nodeId);
            if (node) {
                return node.name;
            }
        }
        
        // 返回默认值
        return nodeId.substring(0, 8) + '...';
    }
    
    /**
     * 记录材质使用（当应用材质到mesh时调用）
     * @param {string} materialId - 材质ID
     * @param {string} sceneId - 场景ID
     * @param {string} nodeId - 节点ID
     * @param {string} nodeName - 节点名称
     * @param {string} meshUuid - Mesh UUID
     * @param {string} meshName - Mesh名称
     */
    async recordMaterialUsage(materialId, sceneId, nodeId, nodeName, meshUuid, meshName) {
        // 确保材质ID存在
        if (!this.materialUsageMap.has(materialId)) {
            this.materialUsageMap.set(materialId, new Map());
        }
        
        const materialScenes = this.materialUsageMap.get(materialId);
        
        // 确保场景ID存在
        if (!materialScenes.has(sceneId)) {
            materialScenes.set(sceneId, new Map());
        }
        
        const sceneNodes = materialScenes.get(sceneId);
        
        // 确保节点ID存在
        const isNewNode = !sceneNodes.has(nodeId);
        if (isNewNode) {
            sceneNodes.set(nodeId, {
                nodeName,
                meshes: new Map() // ⭐ 改用Map，key为meshUuid
            });
        }
        
        const nodeData = sceneNodes.get(nodeId);
        
        // ⭐⭐ 修复：确保meshes是Map类型（兼容旧数据结构）
        if (!(nodeData.meshes instanceof Map)) {
            // 如果是数组或其他类型，转换为Map
            const oldMeshes = nodeData.meshes;
            nodeData.meshes = new Map();
            
            // 如果原来是数组，迁移数据
            if (Array.isArray(oldMeshes)) {
                oldMeshes.forEach(mesh => {
                    nodeData.meshes.set(mesh.uuid || mesh.meshId, {
                        uuid: mesh.uuid || mesh.meshId,
                        name: mesh.name || mesh.meshName
                    });
                });
            }
        }
        
        // ⭐ 只在不存在时添加mesh，避免重复记录
        if (!nodeData.meshes.has(meshUuid)) {
            nodeData.meshes.set(meshUuid, {
                uuid: meshUuid,
                name: meshName || meshUuid.substr(0, 8)
            });
        } else {
        }
        
        // 🔄 更新材质引用到后端（每个mesh都要记录）
        if (this.projectId) {
            try {
                await addMaterialReference(this.projectId, materialId, sceneId, nodeId, meshUuid, meshName);
                
                // ⭐ 更新前端内存中的材质数据
                const material = this.materials.find(m => m.displayName === materialId || m.name === materialId);
                if (material) {
                    // 确保usedByMeshes数组存在
                    if (!material.usedByMeshes) {
                        material.usedByMeshes = [];
                    }
                    
                    // 检查是否已经存在此引用（避免重复）
                    const existingRef = material.usedByMeshes.find(ref => 
                        ref.sceneId === sceneId && ref.nodeId === nodeId && ref.meshId === meshUuid
                    );
                    
                    if (!existingRef) {
                        material.usedByMeshes.push({
                            sceneId,
                            nodeId,
                            meshId: meshUuid,
                            meshName: meshName
                        });
                    }
                }
                
                // ⭐ 刷新UI显示
                this.refreshMaterialUsageDisplay();
            } catch (error) {
                console.warn('⚠️ [MaterialEditorPanel] 更新材质引用失败:', error);
            }
        }
    }
    
    /**
     * 清除材质使用记录（当删除材质绑定时调用）
     * @param {string} materialId - 材质ID
     * @param {string} sceneId - 场景ID
     * @param {string} nodeId - 节点ID
     * @param {string} meshUuid - Mesh UUID
     */
    async removeMaterialUsage(materialId, sceneId, nodeId, meshUuid) {
        if (!this.materialUsageMap.has(materialId)) return;
        
        const materialScenes = this.materialUsageMap.get(materialId);
        if (!materialScenes.has(sceneId)) return;
        
        const sceneNodes = materialScenes.get(sceneId);
        if (!sceneNodes.has(nodeId)) return;
        
        const nodeData = sceneNodes.get(nodeId);
        
        // ⭐⭐ 修复：确保meshes是Map类型
        if (!(nodeData.meshes instanceof Map)) {
            // 如果是数组或其他类型，转换为Map
            const oldMeshes = nodeData.meshes;
            nodeData.meshes = new Map();
            
            // 如果原来是数组或Set，迁移数据
            if (Array.isArray(oldMeshes)) {
                oldMeshes.forEach(mesh => {
                    nodeData.meshes.set(mesh.uuid || mesh.meshId, {
                        uuid: mesh.uuid || mesh.meshId,
                        name: mesh.name || mesh.meshName
                    });
                });
            } else if (oldMeshes instanceof Set) {
                Array.from(oldMeshes).forEach(mesh => {
                    nodeData.meshes.set(mesh.uuid || mesh.meshId, {
                        uuid: mesh.uuid || mesh.meshId,
                        name: mesh.name || mesh.meshName
                    });
                });
            }
        }
        
        // 获取mesh名称（用于后端API调用）
        const meshData = nodeData.meshes.get(meshUuid);
        const meshName = meshData?.name || meshUuid;
        
        // 移除mesh（使用Map的delete方法）
        nodeData.meshes.delete(meshUuid);
        
        // 如果节点没有mesh了，移除节点
        if (nodeData.meshes.size === 0) {
            sceneNodes.delete(nodeId);
        }
        
        // 如果场景没有节点了，移除场景
        if (sceneNodes.size === 0) {
            materialScenes.delete(sceneId);
        }
        
        // 如果材质没有场景了，移除材质
        if (materialScenes.size === 0) {
            this.materialUsageMap.delete(materialId);
        }
        
        // 🔄 调用后端API移除引用
        if (this.projectId) {
            try {
                await removeMaterialReference(this.projectId, materialId, sceneId, nodeId, meshUuid, meshName);
                
                // ⭐ 更新前端内存中的材质数据
                const material = this.materials.find(m => m.displayName === materialId || m.name === materialId);
                if (material && material.usedByMeshes && Array.isArray(material.usedByMeshes)) {
                    material.usedByMeshes = material.usedByMeshes.filter(ref => 
                        !(ref.sceneId === sceneId && ref.nodeId === nodeId && ref.meshId === meshUuid)
                    );
                }
                
                // ⭐ 刷新UI显示
                this.refreshMaterialUsageDisplay();
            } catch (error) {
                console.warn('⚠️ [MaterialEditorPanel] 移除材质引用失败:', error);
            }
        }
    }
    
    /**
     * 清理
     */
    dispose() {
        if (this.animationId) {
            cancelAnimationFrame(this.animationId);
        }
        if (this.previewRenderer) {
            this.previewRenderer.dispose();
        }
        
        // 清理预览浮动窗口
        const floatWindow = document.getElementById('material-preview-float-window');
        if (floatWindow) {
            floatWindow.remove();
        }
        
        // 清空材质使用映射
        this.materialUsageMap.clear();
    }
    
    /**
     * 切换 Z-Fighting 参数面板显示/隐藏
     */
    toggleZFightingParams() {
        const enabled = document.getElementById('mat-zfighting-enabled');
        const paramsPanel = document.querySelector('.param-zfighting-params');
        
        if (enabled && paramsPanel) {
            paramsPanel.style.display = enabled.checked ? 'block' : 'none';
        }
    }
    
    /**
     * 应用 Z-Fighting 预设值
     */
    applyZFightingPreset(value) {
        const factorInput = document.getElementById('mat-zfighting-factor');
        const factorValue = document.getElementById('mat-zfighting-factor-value');
        const unitsInput = document.getElementById('mat-zfighting-units');
        const unitsValue = document.getElementById('mat-zfighting-units-value');
        
        if (factorInput && factorValue && unitsInput && unitsValue) {
            factorInput.value = value;
            factorValue.value = value;
            unitsInput.value = value;
            unitsValue.value = value;
            
            console.log(`🎛️ 材质 Z-Fighting 预设已应用: ${value}`);
        }
    }
}
